issue #179 removed ASMVM but it is available on asmvm branch

llvmbinding
Dibyendu Majumdar 4 years ago
parent 72067c0893
commit 7834343893

@ -3,7 +3,6 @@ project(Ravi)
enable_language(CXX)
enable_language(C)
enable_language(ASM)
enable_testing()
# Get access to CMake helpers
@ -14,7 +13,6 @@ option(LLVM_JIT "Controls whether LLVM JIT compilation will be enabled, default
option(OMR_JIT "Controls whether NanoJIT compilation will be enabled, default is OFF" OFF)
option(STATIC_BUILD "Build static version of Ravi, default is OFF" OFF)
option(COMPUTED_GOTO "Controls whether the interpreter switch will use computed gotos on gcc/clang, default is ON" ON)
option(ASM_VM "Controls whether to use the new VM (not ready yet! so don't turn on)" OFF)
option(LTESTS "Controls whether ltests are enabled in Debug mode; note requires Debug build" ON)
if (LLVM_JIT AND OMR_JIT AND MIR_JIT)
@ -22,12 +20,7 @@ if (LLVM_JIT AND OMR_JIT AND MIR_JIT)
"LLVM_JIT, OMR_JIT and MIR_IT cannot all be set to ON at the same time")
endif ()
if (LLVM_JIT OR OMR_JIT OR MIR_JIT)
# ASM VM is in development and not compatible with anything yet
set(ASM_VM OFF)
endif ()
if (NOT WIN32 AND NOT LLVM_JIT AND NOT OMR_JIT AND NOT ASM_VM)
if (NOT WIN32 AND NOT LLVM_JIT AND NOT OMR_JIT)
set(MIR_JIT ON)
endif ()
@ -43,18 +36,6 @@ if (MIR_JIT)
set(STATIC_BUILD OFF)
endif()
if (ASM_VM)
# For now we switch to static build
# TODO A fix is needed to ensure that in shared library the asm functions are resolved
set(STATIC_BUILD ON)
# LTESTS messes with global state and breaks the ASMVM dispatch table
set(LTESTS OFF)
# Not compatible with JIT modes
set(LLVM_JIT OFF)
set(OMR_JIT OFF)
set(MIR_JIT OFF)
endif ()
if (STATIC_BUILD)
message(STATUS "STATIC library build enabled")
else ()
@ -153,51 +134,11 @@ include_directories("${PROJECT_SOURCE_DIR}/include")
include_directories("${PROJECT_SOURCE_DIR}/dmr_c/src")
if (NOT LTESTS)
# Note that enabling ltests.h messes with global_State and thus interferes with ASM_VM
# Note that enabling ltests.h messes with global_State
message(STATUS "Disabling Lua extended test harness 'ltests'")
add_definitions(-DNO_LUA_DEBUG)
endif ()
if (ASM_VM)
# For now we switch to static build
# TODO A fix is needed to ensure that in shared library the asm functions are resolved
add_definitions(-DRAVI_USE_ASMVM)
set(ASMVM_DEFS ${PROJECT_SOURCE_DIR}/include/ravi_asmvm_defs.h)
if (WIN32 AND NOT CYGWIN)
set(VMMODE peobj)
elseif (APPLE)
set(VMMODE machasm)
else ()
set(VMMODE elfasm)
endif ()
# This macro runs the buildvm command to generate the VM code
macro(add_buildvm_target _target _mode)
add_custom_command(OUTPUT ${_target}
COMMAND ${PROJECT_SOURCE_DIR}/vmbuilder/bin/buildvm ARGS -m ${_mode} -o ${_target} ${ARGN}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${PROJECT_SOURCE_DIR}/vmbuilder/bin/buildvm ${ARGN}
)
endmacro(add_buildvm_target)
# Generate ravi_asmvm.obj / ravi_asmvm.s (obj on Windows)
if (WIN32 AND NOT CYGWIN)
add_buildvm_target(${CMAKE_CURRENT_BINARY_DIR}/ravi_asmvm.obj ${VMMODE})
set(ASMVM_SRC ${CMAKE_CURRENT_BINARY_DIR}/ravi_asmvm.obj)
else ()
add_buildvm_target(${CMAKE_CURRENT_BINARY_DIR}/ravi_asmvm.s ${VMMODE})
set(ASMVM_SRC ${CMAKE_CURRENT_BINARY_DIR}/ravi_asmvm.s)
endif ()
# Generate the ravi_bcdef.h header file
add_buildvm_target(${ASMVM_DEFS} bcdef ${LJLIB_C})
SET(ASMVM_DEPS
${ASMVM_SRC}
${ASMVM_DEFS}
)
endif ()
# define JIT compiler sources
if (LLVM_JIT)
set(LLVM_JIT_SRCS src/ravi_llvmjit.cpp src/ravi_llvmtypes.cpp
@ -432,7 +373,6 @@ add_library(${LIBRAVI_NAME} ${LIBRAVI_BUILD_TYPE}
${DMR_C_HEADERS}
${DMR_C_SRCS}
${DMR_C_JIT_SRCS}
${ASMVM_DEPS}
${MIR_HEADERS}
${MIR_SRCS}
${C2MIR_SRCS}
@ -488,51 +428,43 @@ set(NOJIT_RAVI_SRCS
${DMR_C_JIT_SRCS}
src/ravi_nojit.c)
if (NOT ASM_VM)
set(RAVI_STATICEXEC_TARGET ravi_s)
# We always build a static library without JIT so that
# we can create some default executables
add_library(libravinojit_static
${NOJIT_RAVI_SRCS})
set_target_properties(libravinojit_static PROPERTIES PREFIX "") # As we already prefix with lib
target_link_libraries(libravinojit_static ${EXTRA_LIBRARIES})
# Create a simple NoJIT version of statically linked ravi
# This is sometimes useful in other projects that just need a Lua commandline
# but do not care about the shared library
add_executable(ravi_s
src/lua.c)
target_link_libraries(ravi_s libravinojit_static)
# Ravi VSCode Debug adapter
set(RAVI_DEBUGGER_TARGET ravidebug)
add_executable(${RAVI_DEBUGGER_TARGET}
vscode-debugger/src/ravidebug.c
vscode-debugger/src/json.c
vscode-debugger/src/protocol.c)
target_link_libraries(${RAVI_DEBUGGER_TARGET} libravinojit_static)
# Tests for VSCode Debug Adapter
add_executable(testravidebug
vscode-debugger/src/testravidebug.c
vscode-debugger/src/json.c
vscode-debugger/src/protocol.c)
target_link_libraries(testravidebug libravinojit_static)
add_test(TestRaviDebug testravidebug)
add_executable(test_vm tests/test_vm.c)
target_link_libraries(test_vm ${LIBRAVI_NAME})
add_test(TestVM test_vm)
else ()
# Simple VM tests
add_executable(test_asmvm tests/test_asmvm.c)
target_link_libraries(test_asmvm ${LIBRAVI_NAME})
add_test(TestVM test_asmvm)
endif ()
set(RAVI_STATICEXEC_TARGET ravi_s)
# We always build a static library without JIT so that
# we can create some default executables
add_library(libravinojit_static
${NOJIT_RAVI_SRCS})
set_target_properties(libravinojit_static PROPERTIES PREFIX "") # As we already prefix with lib
target_link_libraries(libravinojit_static ${EXTRA_LIBRARIES})
# Create a simple NoJIT version of statically linked ravi
# This is sometimes useful in other projects that just need a Lua commandline
# but do not care about the shared library
add_executable(ravi_s
src/lua.c)
target_link_libraries(ravi_s libravinojit_static)
# Ravi VSCode Debug adapter
set(RAVI_DEBUGGER_TARGET ravidebug)
add_executable(${RAVI_DEBUGGER_TARGET}
vscode-debugger/src/ravidebug.c
vscode-debugger/src/json.c
vscode-debugger/src/protocol.c)
target_link_libraries(${RAVI_DEBUGGER_TARGET} libravinojit_static)
# Tests for VSCode Debug Adapter
add_executable(testravidebug
vscode-debugger/src/testravidebug.c
vscode-debugger/src/json.c
vscode-debugger/src/protocol.c)
target_link_libraries(testravidebug libravinojit_static)
add_test(TestRaviDebug testravidebug)
add_executable(test_vm tests/test_vm.c)
target_link_libraries(test_vm ${LIBRAVI_NAME})
add_test(TestVM test_vm)
configure_file(ravi-config.cmake.in ravi-config.cmake @ONLY)
if (WIN32)

@ -1,4 +0,0 @@
mkdir asmvm
cd asmvm
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi-asmvm -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DASM_VM=ON -G "Visual Studio 15 2017 Win64" ..
cd ..

@ -1,3 +0,0 @@
mkdir buildasmvm
cd buildasmvm
cmake -DSTATIC_BUILD=ON -DASM_VM=ON -DCMAKE_BUILD_TYPE=Debug -DCOMPUTED_GOTO=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..

@ -642,12 +642,6 @@ typedef struct Table {
*/
#define luaO_nilobject (&luaO_nilobject_)
/* Internal assembler functions. Never call these directly from C.
Note that such functions do not follow calling conventions and
are only used by ASM VM to implement bytecodes */
typedef void(*ASMFunction)(void);
LUAI_DDEC const TValue luaO_nilobject_;
/* size of buffer for 'luaO_utf8esc' function */

@ -178,7 +178,6 @@ typedef struct global_State {
TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
/* RAVI additions */
ravi_State *ravi_state;
ASMFunction dispatch[NUM_OPCODES]; /* Dispatch table for ASM VM - wip */
ravi_Writeline ravi_writeline;
ravi_Writestring ravi_writestring;
ravi_Writestringerror ravi_writestringerror;
@ -190,9 +189,6 @@ typedef struct global_State {
#endif
} global_State;
/* Offset of the ASM VM dispatch table */
#define DISPATCH_OFFSET ((int)offsetof(global_State, dispatch))
/*
** 'per thread' state
*/

@ -1,21 +0,0 @@
local tests = {}
tests.RETURN = function()
return
end
tests.LOADK = function()
return 1, 4.2, 'hello'
end
tests.MOVE = function(a, b)
local c,d = a,b
return c,d
end
for k,v in pairs(tests) do
print(k)
ravi.dumplua(v)
--v()
end

@ -582,28 +582,6 @@ static void stackerror (lua_State *L) {
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
#ifdef RAVI_USE_ASMVM
/* following is a temporary solution to decide whether we can use ASM VM.
The symbol ravi_luaV_interp() is generated by the VMBuilder component.
*/
extern int ravi_luaV_interp(lua_State * L);
int asvm_compatible(Proto *p) {
static unsigned char opcodes_supported[NUM_OPCODES] = {
[OP_RETURN] = 1,
[OP_LOADK] = 1,
[OP_MOVE] = 1,
[OP_RAVI_FORLOOP_IP] = 1,
[OP_RAVI_FORLOOP_I1] = 1,
[OP_RAVI_FORPREP_I1] = 1,
[OP_RAVI_FORPREP_IP] = 1};
for (int i = 0; i < p->sizecode; i++) {
int op = GET_OPCODE(p->code[i]);
if (!opcodes_supported[op]) return 0;
}
return 1;
}
#endif
/*
** Call a function (C or Lua). The function to be called is at *func.
** The arguments are on the stack, right after the function.
@ -614,21 +592,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
if (++L->nCcalls >= LUAI_MAXCCALLS)
stackerror(L);
if (!luaD_precall(L, func, nResults, 0)) /* is a Lua function? */ {
#ifdef RAVI_USE_ASMVM
// This is a temporary hack to test the under development ASM VM.
CallInfo *ci = L->ci;
LClosure *cl = clLvalue(ci->func); /* local reference to function's closure */
if (cl->p->sizecode <= 10 &&
asvm_compatible(cl->p)) {
fprintf(stderr, "Invoking ASM VM\n");
ravi_luaV_interp(L);
}
else {
luaV_execute(L); /* call it */
}
#else
luaV_execute(L); /* call it */
#endif
}
L->nCcalls--;
}

@ -28,10 +28,6 @@
#include "ltable.h"
#include "ltm.h"
#ifdef RAVI_USE_ASMVM
#include "ravi_asmvm_defs.h"
#endif
#include "ravijit.h"
#include "ravi_profile.h"
#include "ravi_alloc.h"
@ -340,23 +336,6 @@ void raviE_default_writestringerror(const char *fmt, const char *p) {
fflush(stderr);
}
#ifdef RAVI_USE_ASMVM
/* Initialize dispatch table used by the ASM VM */
static void dispatch_init(global_State *G) {
ASMFunction *disp = G->dispatch;
for (uint32_t i = 0; i < NUM_OPCODES; i++) {
/*
Following computes an offset for the assembly routine for the given OpCode.
The offset is relative to the global symbol ravi_vm_asm_begin that is
generated as part of the VMBuilder code generation. All the bytecode
routines are at some offset to this global symbol.
*/
/* NOTE: enabling ltests.h modifies the global_State and breaks the assumptions abou the location of the dispatch table */
disp[i] = makeasmfunc(ravi_bytecode_offsets[i]);
}
}
#endif
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
int i;
lua_State *L;
@ -406,10 +385,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
close_state(L);
L = NULL;
}
#ifdef RAVI_USE_ASMVM
/* setup dispatch table - this is only used by the new ASM VM - see vmbuilder */
dispatch_init(g);
#endif
#if RAVI_BYTECODE_PROFILING_ENABLED
raviV_init_profiledata(L);
#endif

@ -1,173 +0,0 @@
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <inttypes.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "lobject.h"
#ifndef RAVI_USE_ASMVM
#error This file can only be compiled with ASMVM
#endif
struct MyValue {
int type;
union {
lua_Integer i;
lua_Number n;
const char *s;
} u;
};
/**
* Compiles the given code and invokes it, passing params to it.
* Checks that the code returns given number of values that match expected
* results. Returns 0 if no error.
*/
static int do_asmvm_test(
const char *code, /* code to compiled and invoked */
int nparams, struct MyValue *params, /* parameters */
int nresults, struct MyValue *expected) /* expected return values */
{
int rc = 0;
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L); /* open standard libraries */
if (luaL_loadbuffer(L, code, strlen(code), "chunk") != 0) {
rc = 1;
fprintf(stderr, "Failed to load chunk: %s\n", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
goto Lerror;
}
if (lua_pcall(L, 0, 1, 0) != 0) {
rc = 1;
fprintf(stderr, "Failed to run chunk: %s\n", lua_tostring(L, -1));
goto Lerror;
}
if (!lua_isfunction(L, -1)) {
rc = 1;
fprintf(stderr, "Script did not return a function\n");
goto Lerror;
}
for (int i = 0; i < nparams; i++) {
switch (params[i].type) {
case RAVI_TNUMINT:
lua_pushinteger(L, params[i].u.i);
break;
case RAVI_TNUMFLT:
lua_pushnumber(L, params[i].u.n);
break;
case RAVI_TSTRING:
lua_pushstring(L, params[i].u.s);
break;
default:
fprintf(stderr, "Unsupported argument type %d\n", params[i].type);
rc = 1;
goto Lerror;
}
}
if (lua_pcall(L, nparams, nresults, 0) != 0) {
rc = 1;
fprintf(stderr, "Test function failed: %s\n", lua_tostring(L, -1));
goto Lerror;
}
for (int i = nresults - 1, j = -1; i >= 0; i--, j--) {
switch (expected[i].type) {
case RAVI_TNUMINT: {
if (!lua_isinteger(L, j)) {
fprintf(stderr, "Result %d was expected to be integer\n", i + 1);
rc = 1;
goto Lerror;
}
lua_Integer num = lua_tointeger(L, j);
if (num != expected[i].u.i) {
fprintf(stderr, "Result %d was expected to be %d, but got %d\n", i + 1, (int)expected[i].u.i, (int)num);
rc = 1;
goto Lerror;
}
break;
}
case RAVI_TNUMFLT: {
if (!lua_isnumber(L, j)) {
fprintf(stderr, "Result %d was expected to be number\n", i + 1);
rc = 1;
goto Lerror;
}
lua_Number num = lua_tonumber(L, j);
if (num != expected[i].u.n) {
fprintf(stderr, "Result %d was expected to be %g, but got %g\n", i + 1, expected[i].u.n, num);
rc = 1;
goto Lerror;
}
break;
}
case RAVI_TSTRING: {
if (!lua_isstring(L, j)) {
fprintf(stderr, "Result %d was expected to be string\n", i + 1);
rc = 1;
goto Lerror;
}
const char *s = lua_tostring(L, j);
if (strcmp(s, expected[i].u.s) != 0) {
fprintf(stderr, "Result %d was expected to be %s, but got %s\n", i + 1, expected[i].u.s, s);
rc = 1;
goto Lerror;
}
break;
}
default: {
fprintf(stderr, "Result %d has unexpected type\n", i + 1);
rc = 1;
goto Lerror;
}
}
}
Lerror:
lua_close(L);
return rc;
}
static int test_vm()
{
int failures = 0;
struct MyValue args[3];
struct MyValue results[3];
args[0].type = RAVI_TNUMINT; args[0].u.i = 42;
args[1].type = RAVI_TNUMFLT; args[1].u.n = -4.2;
args[2].type = RAVI_TSTRING; args[2].u.s = "hello";
results[0].type = RAVI_TNUMINT; results[0].u.i = 42;
results[1].type = RAVI_TNUMFLT; results[1].u.n = -4.2;
results[2].type = RAVI_TSTRING; results[2].u.s = "hello";
failures = do_asmvm_test("return function() end", 0, NULL, 0, NULL); // OP_RETURN
failures += do_asmvm_test("return function() return 42 end", 0, NULL, 1, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function() return 42, -4.2 end", 0, NULL, 2, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function() return 42, -4.2, 'hello' end", 0, NULL, 3, results); // OP_LOADK, OP_RETURN
failures += do_asmvm_test("return function(a) local b = a; return b end", 1, args, 1, results); // OP_MOVE, OP_RETURN
failures += do_asmvm_test("return function(a,c) local b,d = a,c; return b,d end", 2, args, 2, results); // OP_MOVE, OP_RETURN
results[0].u.i = 5;
failures += do_asmvm_test("return function (a) for i=1,5 do a=i; end return a end", 0, NULL, 1, results); // OP_LOADK, OP_MOVE, OP_RETURN, OP_RAVI_FOPREP_I1, OP_RAVI_FORLOOP_I1
results[0].u.i = 3;
failures += do_asmvm_test("return function (a) for i=1,4,2 do a=i; end return a end", 0, NULL, 1, results); // OP_LOADK, OP_MOVE, OP_RETURN, OP_RAVI_FOPREP_IP, OP_RAVI_FORLOOP_IP
return failures;
}
int main()
{
int failures = 0;
failures += test_vm();
if (failures)
printf("FAILED\n");
else
printf("OK\n");
return failures ? 1 : 0;
}

@ -1,59 +0,0 @@
This code contains portions of the LuaJIT project. The copyrights for LuaJIT
are reproduced below.
===============================================================================
LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
Copyright (C) 2005-2017 Mike Pall. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
===============================================================================
[ LuaJIT includes code from Lua 5.1/5.2, which has this license statement: ]
Copyright (C) 1994-2012 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================================================
[ LuaJIT includes code from dlmalloc, which has this license statement: ]
This is a version (aka dlmalloc) of malloc/free/realloc written by
Doug Lea and released to the public domain, as explained at
http://creativecommons.org/licenses/publicdomain
===============================================================================

@ -1,24 +0,0 @@
This is a new initiative to build a VM for Ravi/Lua 5.3 using techniques similar to LuaJIT.
Note: This work is temporarily on hold due to changes in bytecode encoding.
Goals
=====
* Create a new Lua/Ravi interpreter that is coded mostly in assembly
* Initial work will focus on X86-64 architecture only
* The VM will support the extended bytecode set of Ravi
* An equally important goal is to document the effort so that it is easier for others to understand how the VM is implemented
Design Notes
============
* `Notes on LuaJIT <https://github.com/dibyendumajumdar/ravi/blob/master/vmbuilder/docs/luajit_buildvm.rst>`_
* `VM Design and Implementation Notes <https://github.com/dibyendumajumdar/ravi/blob/master/vmbuilder/docs/vm-design.rst>`_
Timescales
==========
This project will proceed slowly as this is my first foray into assembly language programming. Also I can only spend time on this project in my free time (i.e. weekends and holidays).
Acknowledgements
================
I plan to reuse parts of LuaJIT / dynasm for this project.

@ -1,844 +0,0 @@
ravi.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <ravi_BC_MOVE>:
0: 0f b6 cc movzbl %ah,%ecx
3: c1 e8 10 shr $0x10,%eax
6: 0f b6 d4 movzbl %ah,%edx
9: c1 e2 04 shl $0x4,%edx
c: 4d 8d 14 10 lea (%r8,%rdx,1),%r10
10: c1 e1 04 shl $0x4,%ecx
13: 4d 8d 1c 08 lea (%r8,%rcx,1),%r11
17: 49 8b 02 mov (%r10),%rax
1a: 45 8b 4a 08 mov 0x8(%r10),%r9d
1e: 49 89 03 mov %rax,(%r11)
21: 45 89 4b 08 mov %r9d,0x8(%r11)
25: 8b 03 mov (%rbx),%eax
27: 0f b6 d0 movzbl %al,%edx
2a: 48 83 c3 04 add $0x4,%rbx
2e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000032 <ravi_BC_LOADK>:
32: 0f b6 cc movzbl %ah,%ecx
35: c1 e8 10 shr $0x10,%eax
38: 0f b7 d0 movzwl %ax,%edx
3b: c1 e2 04 shl $0x4,%edx
3e: 4d 8d 14 17 lea (%r15,%rdx,1),%r10
42: c1 e1 04 shl $0x4,%ecx
45: 4d 8d 1c 08 lea (%r8,%rcx,1),%r11
49: 49 8b 02 mov (%r10),%rax
4c: 45 8b 4a 08 mov 0x8(%r10),%r9d
50: 49 89 03 mov %rax,(%r11)
53: 45 89 4b 08 mov %r9d,0x8(%r11)
57: 8b 03 mov (%rbx),%eax
59: 0f b6 d0 movzbl %al,%edx
5c: 48 83 c3 04 add $0x4,%rbx
60: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000064 <ravi_BC_LOADKX>:
64: 8b 03 mov (%rbx),%eax
66: 0f b6 d0 movzbl %al,%edx
69: 48 83 c3 04 add $0x4,%rbx
6d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000071 <ravi_BC_LOADBOOL>:
71: 8b 03 mov (%rbx),%eax
73: 0f b6 d0 movzbl %al,%edx
76: 48 83 c3 04 add $0x4,%rbx
7a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000007e <ravi_BC_LOADNIL>:
7e: 8b 03 mov (%rbx),%eax
80: 0f b6 d0 movzbl %al,%edx
83: 48 83 c3 04 add $0x4,%rbx
87: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000008b <ravi_BC_GETUPVAL>:
8b: 8b 03 mov (%rbx),%eax
8d: 0f b6 d0 movzbl %al,%edx
90: 48 83 c3 04 add $0x4,%rbx
94: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000098 <ravi_BC_GETTABUP>:
98: 8b 03 mov (%rbx),%eax
9a: 0f b6 d0 movzbl %al,%edx
9d: 48 83 c3 04 add $0x4,%rbx
a1: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000000a5 <ravi_BC_GETTABLE>:
a5: 8b 03 mov (%rbx),%eax
a7: 0f b6 d0 movzbl %al,%edx
aa: 48 83 c3 04 add $0x4,%rbx
ae: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000000b2 <ravi_BC_SETTABUP>:
b2: 8b 03 mov (%rbx),%eax
b4: 0f b6 d0 movzbl %al,%edx
b7: 48 83 c3 04 add $0x4,%rbx
bb: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000000bf <ravi_BC_SETUPVAL>:
bf: 8b 03 mov (%rbx),%eax
c1: 0f b6 d0 movzbl %al,%edx
c4: 48 83 c3 04 add $0x4,%rbx
c8: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000000cc <ravi_BC_SETTABLE>:
cc: 8b 03 mov (%rbx),%eax
ce: 0f b6 d0 movzbl %al,%edx
d1: 48 83 c3 04 add $0x4,%rbx
d5: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000000d9 <ravi_BC_NEWTABLE>:
d9: 8b 03 mov (%rbx),%eax
db: 0f b6 d0 movzbl %al,%edx
de: 48 83 c3 04 add $0x4,%rbx
e2: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000000e6 <ravi_BC_SELF>:
e6: 8b 03 mov (%rbx),%eax
e8: 0f b6 d0 movzbl %al,%edx
eb: 48 83 c3 04 add $0x4,%rbx
ef: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000000f3 <ravi_BC_ADD>:
f3: 8b 03 mov (%rbx),%eax
f5: 0f b6 d0 movzbl %al,%edx
f8: 48 83 c3 04 add $0x4,%rbx
fc: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000100 <ravi_BC_SUB>:
100: 8b 03 mov (%rbx),%eax
102: 0f b6 d0 movzbl %al,%edx
105: 48 83 c3 04 add $0x4,%rbx
109: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000010d <ravi_BC_MUL>:
10d: 8b 03 mov (%rbx),%eax
10f: 0f b6 d0 movzbl %al,%edx
112: 48 83 c3 04 add $0x4,%rbx
116: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000011a <ravi_BC_MOD>:
11a: 8b 03 mov (%rbx),%eax
11c: 0f b6 d0 movzbl %al,%edx
11f: 48 83 c3 04 add $0x4,%rbx
123: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000127 <ravi_BC_POW>:
127: 8b 03 mov (%rbx),%eax
129: 0f b6 d0 movzbl %al,%edx
12c: 48 83 c3 04 add $0x4,%rbx
130: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000134 <ravi_BC_DIV>:
134: 8b 03 mov (%rbx),%eax
136: 0f b6 d0 movzbl %al,%edx
139: 48 83 c3 04 add $0x4,%rbx
13d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000141 <ravi_BC_IDIV>:
141: 8b 03 mov (%rbx),%eax
143: 0f b6 d0 movzbl %al,%edx
146: 48 83 c3 04 add $0x4,%rbx
14a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000014e <ravi_BC_BAND>:
14e: 8b 03 mov (%rbx),%eax
150: 0f b6 d0 movzbl %al,%edx
153: 48 83 c3 04 add $0x4,%rbx
157: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000015b <ravi_BC_BOR>:
15b: 8b 03 mov (%rbx),%eax
15d: 0f b6 d0 movzbl %al,%edx
160: 48 83 c3 04 add $0x4,%rbx
164: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000168 <ravi_BC_BXOR>:
168: 8b 03 mov (%rbx),%eax
16a: 0f b6 d0 movzbl %al,%edx
16d: 48 83 c3 04 add $0x4,%rbx
171: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000175 <ravi_BC_SHL>:
175: 8b 03 mov (%rbx),%eax
177: 0f b6 d0 movzbl %al,%edx
17a: 48 83 c3 04 add $0x4,%rbx
17e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000182 <ravi_BC_SHR>:
182: 8b 03 mov (%rbx),%eax
184: 0f b6 d0 movzbl %al,%edx
187: 48 83 c3 04 add $0x4,%rbx
18b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000018f <ravi_BC_UNM>:
18f: 8b 03 mov (%rbx),%eax
191: 0f b6 d0 movzbl %al,%edx
194: 48 83 c3 04 add $0x4,%rbx
198: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000019c <ravi_BC_BNOT>:
19c: 8b 03 mov (%rbx),%eax
19e: 0f b6 d0 movzbl %al,%edx
1a1: 48 83 c3 04 add $0x4,%rbx
1a5: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000001a9 <ravi_BC_NOT>:
1a9: 8b 03 mov (%rbx),%eax
1ab: 0f b6 d0 movzbl %al,%edx
1ae: 48 83 c3 04 add $0x4,%rbx
1b2: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000001b6 <ravi_BC_LEN>:
1b6: 8b 03 mov (%rbx),%eax
1b8: 0f b6 d0 movzbl %al,%edx
1bb: 48 83 c3 04 add $0x4,%rbx
1bf: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000001c3 <ravi_BC_CONCAT>:
1c3: 8b 03 mov (%rbx),%eax
1c5: 0f b6 d0 movzbl %al,%edx
1c8: 48 83 c3 04 add $0x4,%rbx
1cc: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000001d0 <ravi_BC_JMP>:
1d0: 8b 03 mov (%rbx),%eax
1d2: 0f b6 d0 movzbl %al,%edx
1d5: 48 83 c3 04 add $0x4,%rbx
1d9: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000001dd <ravi_BC_EQ>:
1dd: 8b 03 mov (%rbx),%eax
1df: 0f b6 d0 movzbl %al,%edx
1e2: 48 83 c3 04 add $0x4,%rbx
1e6: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000001ea <ravi_BC_LT>:
1ea: 8b 03 mov (%rbx),%eax
1ec: 0f b6 d0 movzbl %al,%edx
1ef: 48 83 c3 04 add $0x4,%rbx
1f3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000001f7 <ravi_BC_LE>:
1f7: 8b 03 mov (%rbx),%eax
1f9: 0f b6 d0 movzbl %al,%edx
1fc: 48 83 c3 04 add $0x4,%rbx
200: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000204 <ravi_BC_TEST>:
204: 8b 03 mov (%rbx),%eax
206: 0f b6 d0 movzbl %al,%edx
209: 48 83 c3 04 add $0x4,%rbx
20d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000211 <ravi_BC_TESTSET>:
211: 8b 03 mov (%rbx),%eax
213: 0f b6 d0 movzbl %al,%edx
216: 48 83 c3 04 add $0x4,%rbx
21a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000021e <ravi_BC_CALL>:
21e: 8b 03 mov (%rbx),%eax
220: 0f b6 d0 movzbl %al,%edx
223: 48 83 c3 04 add $0x4,%rbx
227: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000022b <ravi_BC_TAILCALL>:
22b: 8b 03 mov (%rbx),%eax
22d: 0f b6 d0 movzbl %al,%edx
230: 48 83 c3 04 add $0x4,%rbx
234: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000238 <ravi_BC_RETURN>:
238: 4d 8b 55 18 mov 0x18(%r13),%r10
23c: 41 83 7a 20 00 cmpl $0x0,0x20(%r10)
241: 74 17 je 25a <ravi_BC_RETURN+0x22>
243: 49 89 c7 mov %rax,%r15
246: 4d 89 c5 mov %r8,%r13
249: 48 89 ef mov %rbp,%rdi
24c: 4c 89 c6 mov %r8,%rsi
24f: e8 00 00 00 00 callq 254 <ravi_BC_RETURN+0x1c>
254: 4d 89 e8 mov %r13,%r8
257: 4c 89 f8 mov %r15,%rax
25a: 49 89 5c 24 28 mov %rbx,0x28(%r12)
25f: 0f b6 cc movzbl %ah,%ecx
262: c1 e8 10 shr $0x10,%eax
265: 0f b6 d4 movzbl %ah,%edx
268: 41 89 ca mov %ecx,%r10d
26b: 85 d2 test %edx,%edx
26d: 74 0e je 27d <ravi_BC_RETURN+0x45>
26f: ff ca dec %edx
271: 89 d1 mov %edx,%ecx
273: 41 c1 e2 04 shl $0x4,%r10d
277: 4b 8d 14 10 lea (%r8,%r10,1),%rdx
27b: eb 13 jmp 290 <ravi_BC_RETURN+0x58>
27d: 41 c1 e2 04 shl $0x4,%r10d
281: 4b 8d 14 10 lea (%r8,%r10,1),%rdx
285: 48 8b 4d 10 mov 0x10(%rbp),%rcx
289: 48 29 d1 sub %rdx,%rcx
28c: 48 c1 e9 04 shr $0x4,%rcx
290: 48 89 ef mov %rbp,%rdi
293: 4c 89 e6 mov %r12,%rsi
296: e8 00 00 00 00 callq 29b <ravi_BC_RETURN+0x63>
29b: 66 41 f7 44 24 42 08 testw $0x8,0x42(%r12)
2a2: 00
2a3: 0f 85 fa 04 00 00 jne 7a3 <ravi_vm_return>
2a9: 4c 8b 65 20 mov 0x20(%rbp),%r12
2ad: 85 c0 test %eax,%eax
2af: 74 09 je 2ba <ravi_BC_RETURN+0x82>
2b1: 4d 8b 6c 24 08 mov 0x8(%r12),%r13
2b6: 4c 89 6d 10 mov %r13,0x10(%rbp)
2ba: e9 be 04 00 00 jmpq 77d <ravi_new_frame>
00000000000002bf <ravi_BC_FORLOOP>:
2bf: 8b 03 mov (%rbx),%eax
2c1: 0f b6 d0 movzbl %al,%edx
2c4: 48 83 c3 04 add $0x4,%rbx
2c8: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000002cc <ravi_BC_FORPREP>:
2cc: 8b 03 mov (%rbx),%eax
2ce: 0f b6 d0 movzbl %al,%edx
2d1: 48 83 c3 04 add $0x4,%rbx
2d5: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000002d9 <ravi_BC_TFORCALL>:
2d9: 8b 03 mov (%rbx),%eax
2db: 0f b6 d0 movzbl %al,%edx
2de: 48 83 c3 04 add $0x4,%rbx
2e2: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000002e6 <ravi_BC_TFORLOOP>:
2e6: 8b 03 mov (%rbx),%eax
2e8: 0f b6 d0 movzbl %al,%edx
2eb: 48 83 c3 04 add $0x4,%rbx
2ef: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000002f3 <ravi_BC_SETLIST>:
2f3: 8b 03 mov (%rbx),%eax
2f5: 0f b6 d0 movzbl %al,%edx
2f8: 48 83 c3 04 add $0x4,%rbx
2fc: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000300 <ravi_BC_CLOSURE>:
300: 8b 03 mov (%rbx),%eax
302: 0f b6 d0 movzbl %al,%edx
305: 48 83 c3 04 add $0x4,%rbx
309: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000030d <ravi_BC_VARARG>:
30d: 8b 03 mov (%rbx),%eax
30f: 0f b6 d0 movzbl %al,%edx
312: 48 83 c3 04 add $0x4,%rbx
316: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000031a <ravi_BC_EXTRAARG>:
31a: 8b 03 mov (%rbx),%eax
31c: 0f b6 d0 movzbl %al,%edx
31f: 48 83 c3 04 add $0x4,%rbx
323: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000327 <ravi_BC_NEWARRAYI>:
327: 8b 03 mov (%rbx),%eax
329: 0f b6 d0 movzbl %al,%edx
32c: 48 83 c3 04 add $0x4,%rbx
330: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000334 <ravi_BC_NEWARRAYF>:
334: 8b 03 mov (%rbx),%eax
336: 0f b6 d0 movzbl %al,%edx
339: 48 83 c3 04 add $0x4,%rbx
33d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000341 <ravi_BC_LOADIZ>:
341: 8b 03 mov (%rbx),%eax
343: 0f b6 d0 movzbl %al,%edx
346: 48 83 c3 04 add $0x4,%rbx
34a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000034e <ravi_BC_LOADFZ>:
34e: 8b 03 mov (%rbx),%eax
350: 0f b6 d0 movzbl %al,%edx
353: 48 83 c3 04 add $0x4,%rbx
357: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000035b <ravi_BC_UNMF>:
35b: 8b 03 mov (%rbx),%eax
35d: 0f b6 d0 movzbl %al,%edx
360: 48 83 c3 04 add $0x4,%rbx
364: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000368 <ravi_BC_UNMI>:
368: 8b 03 mov (%rbx),%eax
36a: 0f b6 d0 movzbl %al,%edx
36d: 48 83 c3 04 add $0x4,%rbx
371: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000375 <ravi_BC_ADDFF>:
375: 8b 03 mov (%rbx),%eax
377: 0f b6 d0 movzbl %al,%edx
37a: 48 83 c3 04 add $0x4,%rbx
37e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000382 <ravi_BC_ADDFI>:
382: 8b 03 mov (%rbx),%eax
384: 0f b6 d0 movzbl %al,%edx
387: 48 83 c3 04 add $0x4,%rbx
38b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000038f <ravi_BC_ADDII>:
38f: 8b 03 mov (%rbx),%eax
391: 0f b6 d0 movzbl %al,%edx
394: 48 83 c3 04 add $0x4,%rbx
398: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000039c <ravi_BC_SUBFF>:
39c: 8b 03 mov (%rbx),%eax
39e: 0f b6 d0 movzbl %al,%edx
3a1: 48 83 c3 04 add $0x4,%rbx
3a5: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000003a9 <ravi_BC_SUBFI>:
3a9: 8b 03 mov (%rbx),%eax
3ab: 0f b6 d0 movzbl %al,%edx
3ae: 48 83 c3 04 add $0x4,%rbx
3b2: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000003b6 <ravi_BC_SUBIF>:
3b6: 8b 03 mov (%rbx),%eax
3b8: 0f b6 d0 movzbl %al,%edx
3bb: 48 83 c3 04 add $0x4,%rbx
3bf: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000003c3 <ravi_BC_SUBII>:
3c3: 8b 03 mov (%rbx),%eax
3c5: 0f b6 d0 movzbl %al,%edx
3c8: 48 83 c3 04 add $0x4,%rbx
3cc: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000003d0 <ravi_BC_MULFF>:
3d0: 8b 03 mov (%rbx),%eax
3d2: 0f b6 d0 movzbl %al,%edx
3d5: 48 83 c3 04 add $0x4,%rbx
3d9: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000003dd <ravi_BC_MULFI>:
3dd: 8b 03 mov (%rbx),%eax
3df: 0f b6 d0 movzbl %al,%edx
3e2: 48 83 c3 04 add $0x4,%rbx
3e6: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000003ea <ravi_BC_MULII>:
3ea: 8b 03 mov (%rbx),%eax
3ec: 0f b6 d0 movzbl %al,%edx
3ef: 48 83 c3 04 add $0x4,%rbx
3f3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000003f7 <ravi_BC_DIVFF>:
3f7: 8b 03 mov (%rbx),%eax
3f9: 0f b6 d0 movzbl %al,%edx
3fc: 48 83 c3 04 add $0x4,%rbx
400: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000404 <ravi_BC_DIVFI>:
404: 8b 03 mov (%rbx),%eax
406: 0f b6 d0 movzbl %al,%edx
409: 48 83 c3 04 add $0x4,%rbx
40d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000411 <ravi_BC_DIVIF>:
411: 8b 03 mov (%rbx),%eax
413: 0f b6 d0 movzbl %al,%edx
416: 48 83 c3 04 add $0x4,%rbx
41a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000041e <ravi_BC_DIVII>:
41e: 8b 03 mov (%rbx),%eax
420: 0f b6 d0 movzbl %al,%edx
423: 48 83 c3 04 add $0x4,%rbx
427: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000042b <ravi_BC_TOINT>:
42b: 8b 03 mov (%rbx),%eax
42d: 0f b6 d0 movzbl %al,%edx
430: 48 83 c3 04 add $0x4,%rbx
434: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000438 <ravi_BC_TOFLT>:
438: 8b 03 mov (%rbx),%eax
43a: 0f b6 d0 movzbl %al,%edx
43d: 48 83 c3 04 add $0x4,%rbx
441: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000445 <ravi_BC_TOARRAYI>:
445: 8b 03 mov (%rbx),%eax
447: 0f b6 d0 movzbl %al,%edx
44a: 48 83 c3 04 add $0x4,%rbx
44e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000452 <ravi_BC_TOARRAYF>:
452: 8b 03 mov (%rbx),%eax
454: 0f b6 d0 movzbl %al,%edx
457: 48 83 c3 04 add $0x4,%rbx
45b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000045f <ravi_BC_TOTAB>:
45f: 8b 03 mov (%rbx),%eax
461: 0f b6 d0 movzbl %al,%edx
464: 48 83 c3 04 add $0x4,%rbx
468: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000046c <ravi_BC_TOSTRING>:
46c: 8b 03 mov (%rbx),%eax
46e: 0f b6 d0 movzbl %al,%edx
471: 48 83 c3 04 add $0x4,%rbx
475: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000479 <ravi_BC_TOCLOSURE>:
479: 8b 03 mov (%rbx),%eax
47b: 0f b6 d0 movzbl %al,%edx
47e: 48 83 c3 04 add $0x4,%rbx
482: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000486 <ravi_BC_TOTYPE>:
486: 8b 03 mov (%rbx),%eax
488: 0f b6 d0 movzbl %al,%edx
48b: 48 83 c3 04 add $0x4,%rbx
48f: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000493 <ravi_BC_MOVEI>:
493: 8b 03 mov (%rbx),%eax
495: 0f b6 d0 movzbl %al,%edx
498: 48 83 c3 04 add $0x4,%rbx
49c: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000004a0 <ravi_BC_MOVEF>:
4a0: 8b 03 mov (%rbx),%eax
4a2: 0f b6 d0 movzbl %al,%edx
4a5: 48 83 c3 04 add $0x4,%rbx
4a9: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000004ad <ravi_BC_MOVEAI>:
4ad: 8b 03 mov (%rbx),%eax
4af: 0f b6 d0 movzbl %al,%edx
4b2: 48 83 c3 04 add $0x4,%rbx
4b6: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000004ba <ravi_BC_MOVEAF>:
4ba: 8b 03 mov (%rbx),%eax
4bc: 0f b6 d0 movzbl %al,%edx
4bf: 48 83 c3 04 add $0x4,%rbx
4c3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000004c7 <ravi_BC_MOVETAB>:
4c7: 8b 03 mov (%rbx),%eax
4c9: 0f b6 d0 movzbl %al,%edx
4cc: 48 83 c3 04 add $0x4,%rbx
4d0: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000004d4 <ravi_BC_GETTABLE_AI>:
4d4: 8b 03 mov (%rbx),%eax
4d6: 0f b6 d0 movzbl %al,%edx
4d9: 48 83 c3 04 add $0x4,%rbx
4dd: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000004e1 <ravi_BC_GETTABLE_AF>:
4e1: 8b 03 mov (%rbx),%eax
4e3: 0f b6 d0 movzbl %al,%edx
4e6: 48 83 c3 04 add $0x4,%rbx
4ea: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000004ee <ravi_BC_SETTABLE_AI>:
4ee: 8b 03 mov (%rbx),%eax
4f0: 0f b6 d0 movzbl %al,%edx
4f3: 48 83 c3 04 add $0x4,%rbx
4f7: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000004fb <ravi_BC_SETTABLE_AF>:
4fb: 8b 03 mov (%rbx),%eax
4fd: 0f b6 d0 movzbl %al,%edx
500: 48 83 c3 04 add $0x4,%rbx
504: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000508 <ravi_BC_SETTABLE_AII>:
508: 8b 03 mov (%rbx),%eax
50a: 0f b6 d0 movzbl %al,%edx
50d: 48 83 c3 04 add $0x4,%rbx
511: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000515 <ravi_BC_SETTABLE_AFF>:
515: 8b 03 mov (%rbx),%eax
517: 0f b6 d0 movzbl %al,%edx
51a: 48 83 c3 04 add $0x4,%rbx
51e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000522 <ravi_BC_FORLOOP_IP>:
522: 0f b6 cc movzbl %ah,%ecx
525: c1 e1 04 shl $0x4,%ecx
528: 4d 8d 0c 08 lea (%r8,%rcx,1),%r9
52c: 4d 8b 11 mov (%r9),%r10
52f: 4d 03 51 20 add 0x20(%r9),%r10
533: 4d 3b 51 10 cmp 0x10(%r9),%r10
537: 7f 1f jg 558 <ravi_BC_FORLOOP_IP+0x36>
539: 4d 89 11 mov %r10,(%r9)
53c: 4d 8d 59 30 lea 0x30(%r9),%r11
540: 4d 89 13 mov %r10,(%r11)
543: 66 41 c7 43 08 13 00 movw $0x13,0x8(%r11)
54a: c1 e8 10 shr $0x10,%eax
54d: 0f b7 d0 movzwl %ax,%edx
550: 48 8d 9c 93 00 00 fe lea -0x20000(%rbx,%rdx,4),%rbx
557: ff
558: 8b 03 mov (%rbx),%eax
55a: 0f b6 d0 movzbl %al,%edx
55d: 48 83 c3 04 add $0x4,%rbx
561: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000565 <ravi_BC_FORLOOP_I1>:
565: 0f b6 cc movzbl %ah,%ecx
568: c1 e1 04 shl $0x4,%ecx
56b: 4d 8d 0c 08 lea (%r8,%rcx,1),%r9
56f: 4d 8b 11 mov (%r9),%r10
572: 49 ff c2 inc %r10
575: 4d 3b 51 10 cmp 0x10(%r9),%r10
579: 7f 1f jg 59a <ravi_BC_FORLOOP_I1+0x35>
57b: 4d 89 11 mov %r10,(%r9)
57e: 4d 8d 59 30 lea 0x30(%r9),%r11
582: 4d 89 13 mov %r10,(%r11)
585: 66 41 c7 43 08 13 00 movw $0x13,0x8(%r11)
58c: c1 e8 10 shr $0x10,%eax
58f: 0f b7 d0 movzwl %ax,%edx
592: 48 8d 9c 93 00 00 fe lea -0x20000(%rbx,%rdx,4),%rbx
599: ff
59a: 8b 03 mov (%rbx),%eax
59c: 0f b6 d0 movzbl %al,%edx
59f: 48 83 c3 04 add $0x4,%rbx
5a3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000005a7 <ravi_BC_FORPREP_IP>:
5a7: 0f b6 cc movzbl %ah,%ecx
5aa: c1 e8 10 shr $0x10,%eax
5ad: 0f b7 d0 movzwl %ax,%edx
5b0: c1 e1 04 shl $0x4,%ecx
5b3: 49 8d 04 08 lea (%r8,%rcx,1),%rax
5b7: 4c 8b 10 mov (%rax),%r10
5ba: 4c 2b 50 20 sub 0x20(%rax),%r10
5be: 4c 89 10 mov %r10,(%rax)
5c1: 48 8d 9c 93 00 00 fe lea -0x20000(%rbx,%rdx,4),%rbx
5c8: ff
5c9: 8b 03 mov (%rbx),%eax
5cb: 0f b6 d0 movzbl %al,%edx
5ce: 48 83 c3 04 add $0x4,%rbx
5d2: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000005d6 <ravi_BC_FORPREP_I1>:
5d6: 0f b6 cc movzbl %ah,%ecx
5d9: c1 e8 10 shr $0x10,%eax
5dc: 0f b7 d0 movzwl %ax,%edx
5df: c1 e1 04 shl $0x4,%ecx
5e2: 49 8d 04 08 lea (%r8,%rcx,1),%rax
5e6: 4c 8b 10 mov (%rax),%r10
5e9: 49 ff ca dec %r10
5ec: 4c 89 10 mov %r10,(%rax)
5ef: 48 8d 9c 93 00 00 fe lea -0x20000(%rbx,%rdx,4),%rbx
5f6: ff
5f7: 8b 03 mov (%rbx),%eax
5f9: 0f b6 d0 movzbl %al,%edx
5fc: 48 83 c3 04 add $0x4,%rbx
600: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000604 <ravi_BC_SETUPVALI>:
604: 8b 03 mov (%rbx),%eax
606: 0f b6 d0 movzbl %al,%edx
609: 48 83 c3 04 add $0x4,%rbx
60d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000611 <ravi_BC_SETUPVALF>:
611: 8b 03 mov (%rbx),%eax
613: 0f b6 d0 movzbl %al,%edx
616: 48 83 c3 04 add $0x4,%rbx
61a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000061e <ravi_BC_SETUPVALAI>:
61e: 8b 03 mov (%rbx),%eax
620: 0f b6 d0 movzbl %al,%edx
623: 48 83 c3 04 add $0x4,%rbx
627: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000062b <ravi_BC_SETUPVALAF>:
62b: 8b 03 mov (%rbx),%eax
62d: 0f b6 d0 movzbl %al,%edx
630: 48 83 c3 04 add $0x4,%rbx
634: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000638 <ravi_BC_SETUPVALT>:
638: 8b 03 mov (%rbx),%eax
63a: 0f b6 d0 movzbl %al,%edx
63d: 48 83 c3 04 add $0x4,%rbx
641: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000645 <ravi_BC_BAND_II>:
645: 8b 03 mov (%rbx),%eax
647: 0f b6 d0 movzbl %al,%edx
64a: 48 83 c3 04 add $0x4,%rbx
64e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000652 <ravi_BC_BOR_II>:
652: 8b 03 mov (%rbx),%eax
654: 0f b6 d0 movzbl %al,%edx
657: 48 83 c3 04 add $0x4,%rbx
65b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000065f <ravi_BC_BXOR_II>:
65f: 8b 03 mov (%rbx),%eax
661: 0f b6 d0 movzbl %al,%edx
664: 48 83 c3 04 add $0x4,%rbx
668: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000066c <ravi_BC_SHL_II>:
66c: 8b 03 mov (%rbx),%eax
66e: 0f b6 d0 movzbl %al,%edx
671: 48 83 c3 04 add $0x4,%rbx
675: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000679 <ravi_BC_SHR_II>:
679: 8b 03 mov (%rbx),%eax
67b: 0f b6 d0 movzbl %al,%edx
67e: 48 83 c3 04 add $0x4,%rbx
682: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000686 <ravi_BC_BNOT_I>:
686: 8b 03 mov (%rbx),%eax
688: 0f b6 d0 movzbl %al,%edx
68b: 48 83 c3 04 add $0x4,%rbx
68f: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000693 <ravi_BC_EQ_II>:
693: 8b 03 mov (%rbx),%eax
695: 0f b6 d0 movzbl %al,%edx
698: 48 83 c3 04 add $0x4,%rbx
69c: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000006a0 <ravi_BC_EQ_FF>:
6a0: 8b 03 mov (%rbx),%eax
6a2: 0f b6 d0 movzbl %al,%edx
6a5: 48 83 c3 04 add $0x4,%rbx
6a9: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000006ad <ravi_BC_LT_II>:
6ad: 8b 03 mov (%rbx),%eax
6af: 0f b6 d0 movzbl %al,%edx
6b2: 48 83 c3 04 add $0x4,%rbx
6b6: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000006ba <ravi_BC_LT_FF>:
6ba: 8b 03 mov (%rbx),%eax
6bc: 0f b6 d0 movzbl %al,%edx
6bf: 48 83 c3 04 add $0x4,%rbx
6c3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000006c7 <ravi_BC_LE_II>:
6c7: 8b 03 mov (%rbx),%eax
6c9: 0f b6 d0 movzbl %al,%edx
6cc: 48 83 c3 04 add $0x4,%rbx
6d0: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000006d4 <ravi_BC_LE_FF>:
6d4: 8b 03 mov (%rbx),%eax
6d6: 0f b6 d0 movzbl %al,%edx
6d9: 48 83 c3 04 add $0x4,%rbx
6dd: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000006e1 <ravi_BC_GETTABLE_S>:
6e1: 8b 03 mov (%rbx),%eax
6e3: 0f b6 d0 movzbl %al,%edx
6e6: 48 83 c3 04 add $0x4,%rbx
6ea: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000006ee <ravi_BC_SETTABLE_S>:
6ee: 8b 03 mov (%rbx),%eax
6f0: 0f b6 d0 movzbl %al,%edx
6f3: 48 83 c3 04 add $0x4,%rbx
6f7: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000006fb <ravi_BC_SELF_S>:
6fb: 8b 03 mov (%rbx),%eax
6fd: 0f b6 d0 movzbl %al,%edx
700: 48 83 c3 04 add $0x4,%rbx
704: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000708 <ravi_BC_GETTABLE_I>:
708: 8b 03 mov (%rbx),%eax
70a: 0f b6 d0 movzbl %al,%edx
70d: 48 83 c3 04 add $0x4,%rbx
711: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000715 <ravi_BC_SETTABLE_I>:
715: 8b 03 mov (%rbx),%eax
717: 0f b6 d0 movzbl %al,%edx
71a: 48 83 c3 04 add $0x4,%rbx
71e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000722 <ravi_BC_GETTABLE_SK>:
722: 8b 03 mov (%rbx),%eax
724: 0f b6 d0 movzbl %al,%edx
727: 48 83 c3 04 add $0x4,%rbx
72b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000072f <ravi_BC_SELF_SK>:
72f: 8b 03 mov (%rbx),%eax
731: 0f b6 d0 movzbl %al,%edx
734: 48 83 c3 04 add $0x4,%rbx
738: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
000000000000073c <ravi_BC_SETTABLE_SK>:
73c: 8b 03 mov (%rbx),%eax
73e: 0f b6 d0 movzbl %al,%edx
741: 48 83 c3 04 add $0x4,%rbx
745: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000749 <ravi_BC_GETTABUP_SK>:
749: 8b 03 mov (%rbx),%eax
74b: 0f b6 d0 movzbl %al,%edx
74e: 48 83 c3 04 add $0x4,%rbx
752: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
0000000000000756 <ravi_luaV_interp>:
756: 55 push %rbp
757: 53 push %rbx
758: 41 57 push %r15
75a: 41 56 push %r14
75c: 41 55 push %r13
75e: 41 54 push %r12
760: 48 83 ec 28 sub $0x28,%rsp
764: 48 89 fd mov %rdi,%rbp
767: 4c 8b 75 18 mov 0x18(%rbp),%r14
76b: 49 81 c6 40 05 00 00 add $0x540,%r14
772: 4c 8b 65 20 mov 0x20(%rbp),%r12
776: 66 41 83 4c 24 42 08 orw $0x8,0x42(%r12)
000000000000077d <ravi_new_frame>:
77d: 4d 8b 14 24 mov (%r12),%r10
781: 4d 8b 2a mov (%r10),%r13
784: 4d 8b 44 24 20 mov 0x20(%r12),%r8
789: 49 8b 5d 18 mov 0x18(%r13),%rbx
78d: 4c 8b 7b 30 mov 0x30(%rbx),%r15
791: 49 8b 5c 24 28 mov 0x28(%r12),%rbx
796: 8b 03 mov (%rbx),%eax
798: 0f b6 d0 movzbl %al,%edx
79b: 48 83 c3 04 add $0x4,%rbx
79f: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
00000000000007a3 <ravi_vm_return>:
7a3: 48 83 c4 28 add $0x28,%rsp
7a7: 41 5c pop %r12
7a9: 41 5d pop %r13
7ab: 41 5e pop %r14
7ad: 41 5f pop %r15
7af: 5b pop %rbx
7b0: 5d pop %rbp
7b1: c3 retq

@ -1,995 +0,0 @@
vm.obj: file format COFF-x86-64
Disassembly of section .text:
ravi_vm_asm_begin:
0: 0f b6 cc movzbl %ah, %ecx
3: c1 e8 10 shrl $16, %eax
6: 0f b6 d4 movzbl %ah, %edx
9: c1 e2 04 shll $4, %edx
c: 4d 8d 14 10 leaq (%r8,%rdx), %r10
10: c1 e1 04 shll $4, %ecx
13: 4d 8d 1c 08 leaq (%r8,%rcx), %r11
17: 49 8b 02 movq (%r10), %rax
1a: 45 8b 4a 08 movl 8(%r10), %r9d
1e: 49 89 03 movq %rax, (%r11)
21: 45 89 4b 08 movl %r9d, 8(%r11)
25: 8b 03 movl (%rbx), %eax
27: 0f b6 d0 movzbl %al, %edx
2a: 48 83 c3 04 addq $4, %rbx
2e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LOADK:
32: 0f b6 cc movzbl %ah, %ecx
35: c1 e8 10 shrl $16, %eax
38: 0f b7 d0 movzwl %ax, %edx
3b: c1 e2 04 shll $4, %edx
3e: 4d 8d 14 17 leaq (%r15,%rdx), %r10
42: c1 e1 04 shll $4, %ecx
45: 4d 8d 1c 08 leaq (%r8,%rcx), %r11
49: 49 8b 02 movq (%r10), %rax
4c: 45 8b 4a 08 movl 8(%r10), %r9d
50: 49 89 03 movq %rax, (%r11)
53: 45 89 4b 08 movl %r9d, 8(%r11)
57: 8b 03 movl (%rbx), %eax
59: 0f b6 d0 movzbl %al, %edx
5c: 48 83 c3 04 addq $4, %rbx
60: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LOADKX:
64: 8b 03 movl (%rbx), %eax
66: 0f b6 d0 movzbl %al, %edx
69: 48 83 c3 04 addq $4, %rbx
6d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LOADBOOL:
71: 8b 03 movl (%rbx), %eax
73: 0f b6 d0 movzbl %al, %edx
76: 48 83 c3 04 addq $4, %rbx
7a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LOADNIL:
7e: 8b 03 movl (%rbx), %eax
80: 0f b6 d0 movzbl %al, %edx
83: 48 83 c3 04 addq $4, %rbx
87: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETUPVAL:
8b: 8b 03 movl (%rbx), %eax
8d: 0f b6 d0 movzbl %al, %edx
90: 48 83 c3 04 addq $4, %rbx
94: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETTABUP:
98: 8b 03 movl (%rbx), %eax
9a: 0f b6 d0 movzbl %al, %edx
9d: 48 83 c3 04 addq $4, %rbx
a1: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETTABLE:
a5: 8b 03 movl (%rbx), %eax
a7: 0f b6 d0 movzbl %al, %edx
aa: 48 83 c3 04 addq $4, %rbx
ae: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABUP:
b2: 8b 03 movl (%rbx), %eax
b4: 0f b6 d0 movzbl %al, %edx
b7: 48 83 c3 04 addq $4, %rbx
bb: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETUPVAL:
bf: 8b 03 movl (%rbx), %eax
c1: 0f b6 d0 movzbl %al, %edx
c4: 48 83 c3 04 addq $4, %rbx
c8: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABLE:
cc: 8b 03 movl (%rbx), %eax
ce: 0f b6 d0 movzbl %al, %edx
d1: 48 83 c3 04 addq $4, %rbx
d5: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_NEWTABLE:
d9: 8b 03 movl (%rbx), %eax
db: 0f b6 d0 movzbl %al, %edx
de: 48 83 c3 04 addq $4, %rbx
e2: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SELF:
e6: 8b 03 movl (%rbx), %eax
e8: 0f b6 d0 movzbl %al, %edx
eb: 48 83 c3 04 addq $4, %rbx
ef: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_ADD:
f3: 8b 03 movl (%rbx), %eax
f5: 0f b6 d0 movzbl %al, %edx
f8: 48 83 c3 04 addq $4, %rbx
fc: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SUB:
100: 8b 03 movl (%rbx), %eax
102: 0f b6 d0 movzbl %al, %edx
105: 48 83 c3 04 addq $4, %rbx
109: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MUL:
10d: 8b 03 movl (%rbx), %eax
10f: 0f b6 d0 movzbl %al, %edx
112: 48 83 c3 04 addq $4, %rbx
116: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MOD:
11a: 8b 03 movl (%rbx), %eax
11c: 0f b6 d0 movzbl %al, %edx
11f: 48 83 c3 04 addq $4, %rbx
123: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_POW:
127: 8b 03 movl (%rbx), %eax
129: 0f b6 d0 movzbl %al, %edx
12c: 48 83 c3 04 addq $4, %rbx
130: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_DIV:
134: 8b 03 movl (%rbx), %eax
136: 0f b6 d0 movzbl %al, %edx
139: 48 83 c3 04 addq $4, %rbx
13d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_IDIV:
141: 8b 03 movl (%rbx), %eax
143: 0f b6 d0 movzbl %al, %edx
146: 48 83 c3 04 addq $4, %rbx
14a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_BAND:
14e: 8b 03 movl (%rbx), %eax
150: 0f b6 d0 movzbl %al, %edx
153: 48 83 c3 04 addq $4, %rbx
157: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_BOR:
15b: 8b 03 movl (%rbx), %eax
15d: 0f b6 d0 movzbl %al, %edx
160: 48 83 c3 04 addq $4, %rbx
164: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_BXOR:
168: 8b 03 movl (%rbx), %eax
16a: 0f b6 d0 movzbl %al, %edx
16d: 48 83 c3 04 addq $4, %rbx
171: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SHL:
175: 8b 03 movl (%rbx), %eax
177: 0f b6 d0 movzbl %al, %edx
17a: 48 83 c3 04 addq $4, %rbx
17e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SHR:
182: 8b 03 movl (%rbx), %eax
184: 0f b6 d0 movzbl %al, %edx
187: 48 83 c3 04 addq $4, %rbx
18b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_UNM:
18f: 8b 03 movl (%rbx), %eax
191: 0f b6 d0 movzbl %al, %edx
194: 48 83 c3 04 addq $4, %rbx
198: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_BNOT:
19c: 8b 03 movl (%rbx), %eax
19e: 0f b6 d0 movzbl %al, %edx
1a1: 48 83 c3 04 addq $4, %rbx
1a5: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_NOT:
1a9: 8b 03 movl (%rbx), %eax
1ab: 0f b6 d0 movzbl %al, %edx
1ae: 48 83 c3 04 addq $4, %rbx
1b2: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LEN:
1b6: 8b 03 movl (%rbx), %eax
1b8: 0f b6 d0 movzbl %al, %edx
1bb: 48 83 c3 04 addq $4, %rbx
1bf: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_CONCAT:
1c3: 8b 03 movl (%rbx), %eax
1c5: 0f b6 d0 movzbl %al, %edx
1c8: 48 83 c3 04 addq $4, %rbx
1cc: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_JMP:
1d0: 8b 03 movl (%rbx), %eax
1d2: 0f b6 d0 movzbl %al, %edx
1d5: 48 83 c3 04 addq $4, %rbx
1d9: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_EQ:
1dd: 8b 03 movl (%rbx), %eax
1df: 0f b6 d0 movzbl %al, %edx
1e2: 48 83 c3 04 addq $4, %rbx
1e6: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LT:
1ea: 8b 03 movl (%rbx), %eax
1ec: 0f b6 d0 movzbl %al, %edx
1ef: 48 83 c3 04 addq $4, %rbx
1f3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LE:
1f7: 8b 03 movl (%rbx), %eax
1f9: 0f b6 d0 movzbl %al, %edx
1fc: 48 83 c3 04 addq $4, %rbx
200: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TEST:
204: 8b 03 movl (%rbx), %eax
206: 0f b6 d0 movzbl %al, %edx
209: 48 83 c3 04 addq $4, %rbx
20d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TESTSET:
211: 8b 03 movl (%rbx), %eax
213: 0f b6 d0 movzbl %al, %edx
216: 48 83 c3 04 addq $4, %rbx
21a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_CALL:
21e: 8b 03 movl (%rbx), %eax
220: 0f b6 d0 movzbl %al, %edx
223: 48 83 c3 04 addq $4, %rbx
227: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TAILCALL:
22b: 8b 03 movl (%rbx), %eax
22d: 0f b6 d0 movzbl %al, %edx
230: 48 83 c3 04 addq $4, %rbx
234: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_RETURN:
238: 4d 8b 55 18 movq 24(%r13), %r10
23c: 41 83 7a 20 00 cmpl $0, 32(%r10)
241: 74 17 je 23 <ravi_BC_RETURN+0x22>
243: 49 89 c7 movq %rax, %r15
246: 4d 89 c5 movq %r8, %r13
249: 48 89 e9 movq %rbp, %rcx
24c: 4c 89 c2 movq %r8, %rdx
24f: e8 00 00 00 00 callq 0 <ravi_BC_RETURN+0x1C>
254: 4d 89 e8 movq %r13, %r8
257: 4c 89 f8 movq %r15, %rax
25a: 49 89 5c 24 28 movq %rbx, 40(%r12)
25f: 0f b6 cc movzbl %ah, %ecx
262: c1 e8 10 shrl $16, %eax
265: 0f b6 d4 movzbl %ah, %edx
268: 41 89 ca movl %ecx, %r10d
26b: 85 d2 testl %edx, %edx
26d: 74 0f je 15 <ravi_BC_RETURN+0x46>
26f: ff ca decl %edx
271: 41 89 d1 movl %edx, %r9d
274: 41 c1 e2 04 shll $4, %r10d
278: 4f 8d 04 10 leaq (%r8,%r10), %r8
27c: eb 13 jmp 19 <ravi_BC_RETURN+0x59>
27e: 41 c1 e2 04 shll $4, %r10d
282: 4f 8d 04 10 leaq (%r8,%r10), %r8
286: 4c 8b 4d 10 movq 16(%rbp), %r9
28a: 4d 29 c1 subq %r8, %r9
28d: 49 c1 e9 04 shrq $4, %r9
291: 48 89 e9 movq %rbp, %rcx
294: 4c 89 e2 movq %r12, %rdx
297: e8 00 00 00 00 callq 0 <ravi_BC_RETURN+0x64>
29c: 66 41 f7 44 24 42 08 00 testw $8, 66(%r12)
2a4: 0f 85 fc 04 00 00 jne 1276 <ravi_vm_return>
2aa: 4c 8b 65 20 movq 32(%rbp), %r12
2ae: 85 c0 testl %eax, %eax
2b0: 74 09 je 9 <ravi_BC_RETURN+0x83>
2b2: 4d 8b 6c 24 08 movq 8(%r12), %r13
2b7: 4c 89 6d 10 movq %r13, 16(%rbp)
2bb: e9 c0 04 00 00 jmp 1216 <ravi_new_frame>
ravi_BC_FORLOOP:
2c0: 8b 03 movl (%rbx), %eax
2c2: 0f b6 d0 movzbl %al, %edx
2c5: 48 83 c3 04 addq $4, %rbx
2c9: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_FORPREP:
2cd: 8b 03 movl (%rbx), %eax
2cf: 0f b6 d0 movzbl %al, %edx
2d2: 48 83 c3 04 addq $4, %rbx
2d6: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TFORCALL:
2da: 8b 03 movl (%rbx), %eax
2dc: 0f b6 d0 movzbl %al, %edx
2df: 48 83 c3 04 addq $4, %rbx
2e3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TFORLOOP:
2e7: 8b 03 movl (%rbx), %eax
2e9: 0f b6 d0 movzbl %al, %edx
2ec: 48 83 c3 04 addq $4, %rbx
2f0: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETLIST:
2f4: 8b 03 movl (%rbx), %eax
2f6: 0f b6 d0 movzbl %al, %edx
2f9: 48 83 c3 04 addq $4, %rbx
2fd: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_CLOSURE:
301: 8b 03 movl (%rbx), %eax
303: 0f b6 d0 movzbl %al, %edx
306: 48 83 c3 04 addq $4, %rbx
30a: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_VARARG:
30e: 8b 03 movl (%rbx), %eax
310: 0f b6 d0 movzbl %al, %edx
313: 48 83 c3 04 addq $4, %rbx
317: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_EXTRAARG:
31b: 8b 03 movl (%rbx), %eax
31d: 0f b6 d0 movzbl %al, %edx
320: 48 83 c3 04 addq $4, %rbx
324: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_NEWARRAYI:
328: 8b 03 movl (%rbx), %eax
32a: 0f b6 d0 movzbl %al, %edx
32d: 48 83 c3 04 addq $4, %rbx
331: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_NEWARRAYF:
335: 8b 03 movl (%rbx), %eax
337: 0f b6 d0 movzbl %al, %edx
33a: 48 83 c3 04 addq $4, %rbx
33e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LOADIZ:
342: 8b 03 movl (%rbx), %eax
344: 0f b6 d0 movzbl %al, %edx
347: 48 83 c3 04 addq $4, %rbx
34b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LOADFZ:
34f: 8b 03 movl (%rbx), %eax
351: 0f b6 d0 movzbl %al, %edx
354: 48 83 c3 04 addq $4, %rbx
358: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_UNMF:
35c: 8b 03 movl (%rbx), %eax
35e: 0f b6 d0 movzbl %al, %edx
361: 48 83 c3 04 addq $4, %rbx
365: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_UNMI:
369: 8b 03 movl (%rbx), %eax
36b: 0f b6 d0 movzbl %al, %edx
36e: 48 83 c3 04 addq $4, %rbx
372: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_ADDFF:
376: 8b 03 movl (%rbx), %eax
378: 0f b6 d0 movzbl %al, %edx
37b: 48 83 c3 04 addq $4, %rbx
37f: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_ADDFI:
383: 8b 03 movl (%rbx), %eax
385: 0f b6 d0 movzbl %al, %edx
388: 48 83 c3 04 addq $4, %rbx
38c: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_ADDII:
390: 8b 03 movl (%rbx), %eax
392: 0f b6 d0 movzbl %al, %edx
395: 48 83 c3 04 addq $4, %rbx
399: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SUBFF:
39d: 8b 03 movl (%rbx), %eax
39f: 0f b6 d0 movzbl %al, %edx
3a2: 48 83 c3 04 addq $4, %rbx
3a6: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SUBFI:
3aa: 8b 03 movl (%rbx), %eax
3ac: 0f b6 d0 movzbl %al, %edx
3af: 48 83 c3 04 addq $4, %rbx
3b3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SUBIF:
3b7: 8b 03 movl (%rbx), %eax
3b9: 0f b6 d0 movzbl %al, %edx
3bc: 48 83 c3 04 addq $4, %rbx
3c0: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SUBII:
3c4: 8b 03 movl (%rbx), %eax
3c6: 0f b6 d0 movzbl %al, %edx
3c9: 48 83 c3 04 addq $4, %rbx
3cd: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MULFF:
3d1: 8b 03 movl (%rbx), %eax
3d3: 0f b6 d0 movzbl %al, %edx
3d6: 48 83 c3 04 addq $4, %rbx
3da: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MULFI:
3de: 8b 03 movl (%rbx), %eax
3e0: 0f b6 d0 movzbl %al, %edx
3e3: 48 83 c3 04 addq $4, %rbx
3e7: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MULII:
3eb: 8b 03 movl (%rbx), %eax
3ed: 0f b6 d0 movzbl %al, %edx
3f0: 48 83 c3 04 addq $4, %rbx
3f4: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_DIVFF:
3f8: 8b 03 movl (%rbx), %eax
3fa: 0f b6 d0 movzbl %al, %edx
3fd: 48 83 c3 04 addq $4, %rbx
401: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_DIVFI:
405: 8b 03 movl (%rbx), %eax
407: 0f b6 d0 movzbl %al, %edx
40a: 48 83 c3 04 addq $4, %rbx
40e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_DIVIF:
412: 8b 03 movl (%rbx), %eax
414: 0f b6 d0 movzbl %al, %edx
417: 48 83 c3 04 addq $4, %rbx
41b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_DIVII:
41f: 8b 03 movl (%rbx), %eax
421: 0f b6 d0 movzbl %al, %edx
424: 48 83 c3 04 addq $4, %rbx
428: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TOINT:
42c: 8b 03 movl (%rbx), %eax
42e: 0f b6 d0 movzbl %al, %edx
431: 48 83 c3 04 addq $4, %rbx
435: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TOFLT:
439: 8b 03 movl (%rbx), %eax
43b: 0f b6 d0 movzbl %al, %edx
43e: 48 83 c3 04 addq $4, %rbx
442: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TOARRAYI:
446: 8b 03 movl (%rbx), %eax
448: 0f b6 d0 movzbl %al, %edx
44b: 48 83 c3 04 addq $4, %rbx
44f: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TOARRAYF:
453: 8b 03 movl (%rbx), %eax
455: 0f b6 d0 movzbl %al, %edx
458: 48 83 c3 04 addq $4, %rbx
45c: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TOTAB:
460: 8b 03 movl (%rbx), %eax
462: 0f b6 d0 movzbl %al, %edx
465: 48 83 c3 04 addq $4, %rbx
469: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TOSTRING:
46d: 8b 03 movl (%rbx), %eax
46f: 0f b6 d0 movzbl %al, %edx
472: 48 83 c3 04 addq $4, %rbx
476: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TOCLOSURE:
47a: 8b 03 movl (%rbx), %eax
47c: 0f b6 d0 movzbl %al, %edx
47f: 48 83 c3 04 addq $4, %rbx
483: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_TOTYPE:
487: 8b 03 movl (%rbx), %eax
489: 0f b6 d0 movzbl %al, %edx
48c: 48 83 c3 04 addq $4, %rbx
490: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MOVEI:
494: 8b 03 movl (%rbx), %eax
496: 0f b6 d0 movzbl %al, %edx
499: 48 83 c3 04 addq $4, %rbx
49d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MOVEF:
4a1: 8b 03 movl (%rbx), %eax
4a3: 0f b6 d0 movzbl %al, %edx
4a6: 48 83 c3 04 addq $4, %rbx
4aa: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MOVEAI:
4ae: 8b 03 movl (%rbx), %eax
4b0: 0f b6 d0 movzbl %al, %edx
4b3: 48 83 c3 04 addq $4, %rbx
4b7: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MOVEAF:
4bb: 8b 03 movl (%rbx), %eax
4bd: 0f b6 d0 movzbl %al, %edx
4c0: 48 83 c3 04 addq $4, %rbx
4c4: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_MOVETAB:
4c8: 8b 03 movl (%rbx), %eax
4ca: 0f b6 d0 movzbl %al, %edx
4cd: 48 83 c3 04 addq $4, %rbx
4d1: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETTABLE_AI:
4d5: 8b 03 movl (%rbx), %eax
4d7: 0f b6 d0 movzbl %al, %edx
4da: 48 83 c3 04 addq $4, %rbx
4de: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETTABLE_AF:
4e2: 8b 03 movl (%rbx), %eax
4e4: 0f b6 d0 movzbl %al, %edx
4e7: 48 83 c3 04 addq $4, %rbx
4eb: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABLE_AI:
4ef: 8b 03 movl (%rbx), %eax
4f1: 0f b6 d0 movzbl %al, %edx
4f4: 48 83 c3 04 addq $4, %rbx
4f8: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABLE_AF:
4fc: 8b 03 movl (%rbx), %eax
4fe: 0f b6 d0 movzbl %al, %edx
501: 48 83 c3 04 addq $4, %rbx
505: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABLE_AII:
509: 8b 03 movl (%rbx), %eax
50b: 0f b6 d0 movzbl %al, %edx
50e: 48 83 c3 04 addq $4, %rbx
512: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABLE_AFF:
516: 8b 03 movl (%rbx), %eax
518: 0f b6 d0 movzbl %al, %edx
51b: 48 83 c3 04 addq $4, %rbx
51f: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_FORLOOP_IP:
523: 0f b6 cc movzbl %ah, %ecx
526: c1 e1 04 shll $4, %ecx
529: 4d 8d 0c 08 leaq (%r8,%rcx), %r9
52d: 4d 8b 11 movq (%r9), %r10
530: 4d 03 51 20 addq 32(%r9), %r10
534: 4d 3b 51 10 cmpq 16(%r9), %r10
538: 7f 1f jg 31 <ravi_BC_FORLOOP_IP+0x36>
53a: 4d 89 11 movq %r10, (%r9)
53d: 4d 8d 59 30 leaq 48(%r9), %r11
541: 4d 89 13 movq %r10, (%r11)
544: 66 41 c7 43 08 13 00 movw $19, 8(%r11)
54b: c1 e8 10 shrl $16, %eax
54e: 0f b7 d0 movzwl %ax, %edx
551: 48 8d 9c 93 00 00 fe ff leaq -131072(%rbx,%rdx,4), %rbx
559: 8b 03 movl (%rbx), %eax
55b: 0f b6 d0 movzbl %al, %edx
55e: 48 83 c3 04 addq $4, %rbx
562: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_FORLOOP_I1:
566: 0f b6 cc movzbl %ah, %ecx
569: c1 e1 04 shll $4, %ecx
56c: 4d 8d 0c 08 leaq (%r8,%rcx), %r9
570: 4d 8b 11 movq (%r9), %r10
573: 49 ff c2 incq %r10
576: 4d 3b 51 10 cmpq 16(%r9), %r10
57a: 7f 1f jg 31 <ravi_BC_FORLOOP_I1+0x35>
57c: 4d 89 11 movq %r10, (%r9)
57f: 4d 8d 59 30 leaq 48(%r9), %r11
583: 4d 89 13 movq %r10, (%r11)
586: 66 41 c7 43 08 13 00 movw $19, 8(%r11)
58d: c1 e8 10 shrl $16, %eax
590: 0f b7 d0 movzwl %ax, %edx
593: 48 8d 9c 93 00 00 fe ff leaq -131072(%rbx,%rdx,4), %rbx
59b: 8b 03 movl (%rbx), %eax
59d: 0f b6 d0 movzbl %al, %edx
5a0: 48 83 c3 04 addq $4, %rbx
5a4: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_FORPREP_IP:
5a8: 0f b6 cc movzbl %ah, %ecx
5ab: c1 e8 10 shrl $16, %eax
5ae: 0f b7 d0 movzwl %ax, %edx
5b1: c1 e1 04 shll $4, %ecx
5b4: 49 8d 04 08 leaq (%r8,%rcx), %rax
5b8: 4c 8b 10 movq (%rax), %r10
5bb: 4c 2b 50 20 subq 32(%rax), %r10
5bf: 4c 89 10 movq %r10, (%rax)
5c2: 48 8d 9c 93 00 00 fe ff leaq -131072(%rbx,%rdx,4), %rbx
5ca: 8b 03 movl (%rbx), %eax
5cc: 0f b6 d0 movzbl %al, %edx
5cf: 48 83 c3 04 addq $4, %rbx
5d3: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_FORPREP_I1:
5d7: 0f b6 cc movzbl %ah, %ecx
5da: c1 e8 10 shrl $16, %eax
5dd: 0f b7 d0 movzwl %ax, %edx
5e0: c1 e1 04 shll $4, %ecx
5e3: 49 8d 04 08 leaq (%r8,%rcx), %rax
5e7: 4c 8b 10 movq (%rax), %r10
5ea: 49 ff ca decq %r10
5ed: 4c 89 10 movq %r10, (%rax)
5f0: 48 8d 9c 93 00 00 fe ff leaq -131072(%rbx,%rdx,4), %rbx
5f8: 8b 03 movl (%rbx), %eax
5fa: 0f b6 d0 movzbl %al, %edx
5fd: 48 83 c3 04 addq $4, %rbx
601: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETUPVALI:
605: 8b 03 movl (%rbx), %eax
607: 0f b6 d0 movzbl %al, %edx
60a: 48 83 c3 04 addq $4, %rbx
60e: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETUPVALF:
612: 8b 03 movl (%rbx), %eax
614: 0f b6 d0 movzbl %al, %edx
617: 48 83 c3 04 addq $4, %rbx
61b: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETUPVALAI:
61f: 8b 03 movl (%rbx), %eax
621: 0f b6 d0 movzbl %al, %edx
624: 48 83 c3 04 addq $4, %rbx
628: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETUPVALAF:
62c: 8b 03 movl (%rbx), %eax
62e: 0f b6 d0 movzbl %al, %edx
631: 48 83 c3 04 addq $4, %rbx
635: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETUPVALT:
639: 8b 03 movl (%rbx), %eax
63b: 0f b6 d0 movzbl %al, %edx
63e: 48 83 c3 04 addq $4, %rbx
642: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_BAND_II:
646: 8b 03 movl (%rbx), %eax
648: 0f b6 d0 movzbl %al, %edx
64b: 48 83 c3 04 addq $4, %rbx
64f: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_BOR_II:
653: 8b 03 movl (%rbx), %eax
655: 0f b6 d0 movzbl %al, %edx
658: 48 83 c3 04 addq $4, %rbx
65c: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_BXOR_II:
660: 8b 03 movl (%rbx), %eax
662: 0f b6 d0 movzbl %al, %edx
665: 48 83 c3 04 addq $4, %rbx
669: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SHL_II:
66d: 8b 03 movl (%rbx), %eax
66f: 0f b6 d0 movzbl %al, %edx
672: 48 83 c3 04 addq $4, %rbx
676: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SHR_II:
67a: 8b 03 movl (%rbx), %eax
67c: 0f b6 d0 movzbl %al, %edx
67f: 48 83 c3 04 addq $4, %rbx
683: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_BNOT_I:
687: 8b 03 movl (%rbx), %eax
689: 0f b6 d0 movzbl %al, %edx
68c: 48 83 c3 04 addq $4, %rbx
690: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_EQ_II:
694: 8b 03 movl (%rbx), %eax
696: 0f b6 d0 movzbl %al, %edx
699: 48 83 c3 04 addq $4, %rbx
69d: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_EQ_FF:
6a1: 8b 03 movl (%rbx), %eax
6a3: 0f b6 d0 movzbl %al, %edx
6a6: 48 83 c3 04 addq $4, %rbx
6aa: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LT_II:
6ae: 8b 03 movl (%rbx), %eax
6b0: 0f b6 d0 movzbl %al, %edx
6b3: 48 83 c3 04 addq $4, %rbx
6b7: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LT_FF:
6bb: 8b 03 movl (%rbx), %eax
6bd: 0f b6 d0 movzbl %al, %edx
6c0: 48 83 c3 04 addq $4, %rbx
6c4: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LE_II:
6c8: 8b 03 movl (%rbx), %eax
6ca: 0f b6 d0 movzbl %al, %edx
6cd: 48 83 c3 04 addq $4, %rbx
6d1: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_LE_FF:
6d5: 8b 03 movl (%rbx), %eax
6d7: 0f b6 d0 movzbl %al, %edx
6da: 48 83 c3 04 addq $4, %rbx
6de: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETTABLE_S:
6e2: 8b 03 movl (%rbx), %eax
6e4: 0f b6 d0 movzbl %al, %edx
6e7: 48 83 c3 04 addq $4, %rbx
6eb: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABLE_S:
6ef: 8b 03 movl (%rbx), %eax
6f1: 0f b6 d0 movzbl %al, %edx
6f4: 48 83 c3 04 addq $4, %rbx
6f8: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SELF_S:
6fc: 8b 03 movl (%rbx), %eax
6fe: 0f b6 d0 movzbl %al, %edx
701: 48 83 c3 04 addq $4, %rbx
705: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETTABLE_I:
709: 8b 03 movl (%rbx), %eax
70b: 0f b6 d0 movzbl %al, %edx
70e: 48 83 c3 04 addq $4, %rbx
712: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABLE_I:
716: 8b 03 movl (%rbx), %eax
718: 0f b6 d0 movzbl %al, %edx
71b: 48 83 c3 04 addq $4, %rbx
71f: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETTABLE_SK:
723: 8b 03 movl (%rbx), %eax
725: 0f b6 d0 movzbl %al, %edx
728: 48 83 c3 04 addq $4, %rbx
72c: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SELF_SK:
730: 8b 03 movl (%rbx), %eax
732: 0f b6 d0 movzbl %al, %edx
735: 48 83 c3 04 addq $4, %rbx
739: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_SETTABLE_SK:
73d: 8b 03 movl (%rbx), %eax
73f: 0f b6 d0 movzbl %al, %edx
742: 48 83 c3 04 addq $4, %rbx
746: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_BC_GETTABUP_SK:
74a: 8b 03 movl (%rbx), %eax
74c: 0f b6 d0 movzbl %al, %edx
74f: 48 83 c3 04 addq $4, %rbx
753: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_luaV_interp:
757: 55 pushq %rbp
758: 57 pushq %rdi
759: 56 pushq %rsi
75a: 53 pushq %rbx
75b: 41 54 pushq %r12
75d: 41 55 pushq %r13
75f: 41 56 pushq %r14
761: 41 57 pushq %r15
763: 48 83 ec 28 subq $40, %rsp
767: 48 89 cd movq %rcx, %rbp
76a: 4c 8b 75 18 movq 24(%rbp), %r14
76e: 49 81 c6 40 05 00 00 addq $1344, %r14
775: 4c 8b 65 20 movq 32(%rbp), %r12
779: 66 41 83 4c 24 42 08 orw $8, 66(%r12)
ravi_new_frame:
780: 4d 8b 14 24 movq (%r12), %r10
784: 4d 8b 2a movq (%r10), %r13
787: 4d 8b 44 24 20 movq 32(%r12), %r8
78c: 49 8b 5d 18 movq 24(%r13), %rbx
790: 4c 8b 7b 30 movq 48(%rbx), %r15
794: 49 8b 5c 24 28 movq 40(%r12), %rbx
799: 8b 03 movl (%rbx), %eax
79b: 0f b6 d0 movzbl %al, %edx
79e: 48 83 c3 04 addq $4, %rbx
7a2: 41 ff 24 d6 jmpq *(%r14,%rdx,8)
ravi_vm_return:
7a6: 48 83 c4 28 addq $40, %rsp
7aa: 41 5f popq %r15
7ac: 41 5e popq %r14
7ae: 41 5d popq %r13
7b0: 41 5c popq %r12
7b2: 5b popq %rbx
7b3: 5e popq %rsi
7b4: 5f popq %rdi
7b5: 5d popq %rbp
7b6: c3 retq
SYMBOL TABLE:
[ 0](sec -1)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x00000001 @feat.00
[ 1](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x7b7 nreloc 2 nlnno 0 checksum 0x0 assoc 0 comdat 0
[ 3](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 luaF_close
[ 4](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 luaD_poscall
[ 5](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .pdata
AUX scnlen 0xc nreloc 3 nlnno 0 checksum 0x0 assoc 0 comdat 0
[ 7](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .xdata
AUX scnlen 0x18 nreloc 0 nlnno 0 checksum 0x0 assoc 0 comdat 0
[ 9](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 ravi_vm_asm_begin
[10](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 ravi_BC_MOVE
[11](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000032 ravi_BC_LOADK
[12](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000064 ravi_BC_LOADKX
[13](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000071 ravi_BC_LOADBOOL
[14](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000007e ravi_BC_LOADNIL
[15](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000008b ravi_BC_GETUPVAL
[16](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000098 ravi_BC_GETTABUP
[17](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000000a5 ravi_BC_GETTABLE
[18](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000000b2 ravi_BC_SETTABUP
[19](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000000bf ravi_BC_SETUPVAL
[20](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000000cc ravi_BC_SETTABLE
[21](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000000d9 ravi_BC_NEWTABLE
[22](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000000e6 ravi_BC_SELF
[23](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000000f3 ravi_BC_ADD
[24](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000100 ravi_BC_SUB
[25](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000010d ravi_BC_MUL
[26](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000011a ravi_BC_MOD
[27](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000127 ravi_BC_POW
[28](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000134 ravi_BC_DIV
[29](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000141 ravi_BC_IDIV
[30](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000014e ravi_BC_BAND
[31](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000015b ravi_BC_BOR
[32](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000168 ravi_BC_BXOR
[33](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000175 ravi_BC_SHL
[34](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000182 ravi_BC_SHR
[35](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000018f ravi_BC_UNM
[36](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000019c ravi_BC_BNOT
[37](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000001a9 ravi_BC_NOT
[38](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000001b6 ravi_BC_LEN
[39](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000001c3 ravi_BC_CONCAT
[40](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000001d0 ravi_BC_JMP
[41](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000001dd ravi_BC_EQ
[42](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000001ea ravi_BC_LT
[43](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000001f7 ravi_BC_LE
[44](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000204 ravi_BC_TEST
[45](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000211 ravi_BC_TESTSET
[46](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000021e ravi_BC_CALL
[47](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000022b ravi_BC_TAILCALL
[48](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000238 ravi_BC_RETURN
[49](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000002c0 ravi_BC_FORLOOP
[50](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000002cd ravi_BC_FORPREP
[51](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000002da ravi_BC_TFORCALL
[52](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000002e7 ravi_BC_TFORLOOP
[53](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000002f4 ravi_BC_SETLIST
[54](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000301 ravi_BC_CLOSURE
[55](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000030e ravi_BC_VARARG
[56](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000031b ravi_BC_EXTRAARG
[57](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000328 ravi_BC_NEWARRAYI
[58](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000335 ravi_BC_NEWARRAYF
[59](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000342 ravi_BC_LOADIZ
[60](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000034f ravi_BC_LOADFZ
[61](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000035c ravi_BC_UNMF
[62](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000369 ravi_BC_UNMI
[63](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000376 ravi_BC_ADDFF
[64](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000383 ravi_BC_ADDFI
[65](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000390 ravi_BC_ADDII
[66](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000039d ravi_BC_SUBFF
[67](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000003aa ravi_BC_SUBFI
[68](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000003b7 ravi_BC_SUBIF
[69](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000003c4 ravi_BC_SUBII
[70](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000003d1 ravi_BC_MULFF
[71](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000003de ravi_BC_MULFI
[72](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000003eb ravi_BC_MULII
[73](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000003f8 ravi_BC_DIVFF
[74](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000405 ravi_BC_DIVFI
[75](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000412 ravi_BC_DIVIF
[76](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000041f ravi_BC_DIVII
[77](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000042c ravi_BC_TOINT
[78](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000439 ravi_BC_TOFLT
[79](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000446 ravi_BC_TOARRAYI
[80](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000453 ravi_BC_TOARRAYF
[81](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000460 ravi_BC_TOTAB
[82](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000046d ravi_BC_TOSTRING
[83](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000047a ravi_BC_TOCLOSURE
[84](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000487 ravi_BC_TOTYPE
[85](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000494 ravi_BC_MOVEI
[86](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000004a1 ravi_BC_MOVEF
[87](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000004ae ravi_BC_MOVEAI
[88](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000004bb ravi_BC_MOVEAF
[89](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000004c8 ravi_BC_MOVETAB
[90](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000004d5 ravi_BC_GETTABLE_AI
[91](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000004e2 ravi_BC_GETTABLE_AF
[92](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000004ef ravi_BC_SETTABLE_AI
[93](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000004fc ravi_BC_SETTABLE_AF
[94](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000509 ravi_BC_SETTABLE_AII
[95](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000516 ravi_BC_SETTABLE_AFF
[96](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000523 ravi_BC_FORLOOP_IP
[97](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000566 ravi_BC_FORLOOP_I1
[98](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000005a8 ravi_BC_FORPREP_IP
[99](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000005d7 ravi_BC_FORPREP_I1
[100](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000605 ravi_BC_SETUPVALI
[101](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000612 ravi_BC_SETUPVALF
[102](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000061f ravi_BC_SETUPVALAI
[103](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000062c ravi_BC_SETUPVALAF
[104](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000639 ravi_BC_SETUPVALT
[105](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000646 ravi_BC_BAND_II
[106](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000653 ravi_BC_BOR_II
[107](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000660 ravi_BC_BXOR_II
[108](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000066d ravi_BC_SHL_II
[109](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000067a ravi_BC_SHR_II
[110](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000687 ravi_BC_BNOT_I
[111](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000694 ravi_BC_EQ_II
[112](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000006a1 ravi_BC_EQ_FF
[113](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000006ae ravi_BC_LT_II
[114](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000006bb ravi_BC_LT_FF
[115](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000006c8 ravi_BC_LE_II
[116](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000006d5 ravi_BC_LE_FF
[117](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000006e2 ravi_BC_GETTABLE_S
[118](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000006ef ravi_BC_SETTABLE_S
[119](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000006fc ravi_BC_SELF_S
[120](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000709 ravi_BC_GETTABLE_I
[121](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000716 ravi_BC_SETTABLE_I
[122](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000723 ravi_BC_GETTABLE_SK
[123](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000730 ravi_BC_SELF_SK
[124](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000073d ravi_BC_SETTABLE_SK
[125](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000074a ravi_BC_GETTABUP_SK
[126](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000757 ravi_luaV_interp
[127](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000780 ravi_new_frame
[128](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x000007a6 ravi_vm_return
[129](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .rdata$Z
AUX scnlen 0xd nreloc 0 nlnno 0 checksum 0x0 assoc 0 comdat 0
Unwind info:
Function Table:
Start Address: ravi_vm_asm_begin
End Address: ravi_vm_asm_begin + 0x07b7
Unwind Info Address: .xdata
Version: 1
Flags: 0
Size of prolog: 0
Number of Codes: 9
No frame pointer used
Unwind Codes:
0x00: UOP_AllocSmall 40
0x00: UOP_PushNonVol R15
0x00: UOP_PushNonVol R14
0x00: UOP_PushNonVol R13
0x00: UOP_PushNonVol R12
0x00: UOP_PushNonVol RBX
0x00: UOP_PushNonVol RSI
0x00: UOP_PushNonVol RDI
0x00: UOP_PushNonVol RBP

@ -1,11 +0,0 @@
Assembler output from various compilers
=======================================
The clang output was generated using::
clang -I ~/github/ravi/include -std=c99 -O3 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_COMPAT_5_1 -DLUA_USE_MACOSX -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -DRAVI_USE_ASMVM -DRAVI_USE_COMPUTED_GOTO -S -g -c ~/github/ravi/src/lvm.c
The lvm.s was generated as follows:
objdump -d -M intel -S CMakeFiles/libravinojit_static.dir/src/lvm.c.o > lvm.s

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,35 +0,0 @@
X86-64 calling sequence
=======================
On Windows 64-bit calling sequence requires caller to reserve 32 bytes (for 4 register parameters). See below sequence for example::
subq $32, %rsp
movq %rcx, %rsi
movq 32(%rsi), %rdi
movq (%rdi), %rax
movq 32(%rdi), %rbx
movq (%rax), %rax
movq 24(%rax), %rax
cmpl $0, 32(%rax)
jle .LBB0_2
movabsq $luaF_close, %rax
movq %rsi, %rcx
movq %rbx, %rdx
callq *%rax
.LBB0_2:
movabsq $luaD_poscall, %rax
xorl %r9d, %r9d
movq %rsi, %rcx
movq %rdi, %rdx
movq %rbx, %r8
addq $32, %rsp
References
==========
* `X86-64 Calling conventions <https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions>`_
* `Windows X86-64 Conventions <https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions>`_
Windows Unwind Data
===================
* `Manual Stack Reconstruction <https://blogs.msdn.microsoft.com/ntdebugging/2010/05/12/x64-manual-stack-reconstruction-and-stack-walking/>`_.
* `X84 Deep Dive <http://www.codemachine.com/article_x64deepdive.html>`_ - has useful depiction of unwind info on Win64.

@ -1,29 +0,0 @@
Notes on LuaJIT 2.1 Interpreter VM
==================================
These notes are only for X86-64 architecture.
* The VM code is generated using a number of steps:
1. First the `vm_x86.dasc <https://github.com/LuaJIT/LuaJIT/blob/master/src/vm_x86.dasc>`_ file is processed by dynasm to create the ``buildvm_arch.h`` file.
2. Next the generated ``buildvm_arch.h`` is combined with the ``buildvm`` files to create a custom VM code generator called ``buildvm``.
3. The ``buildvm`` tool is run to output the VM code. The output is an object file in the case of Windows, but on UNIX machines the output is assembly code; however, this file does not contain human readable assembly code - instead the code is output as a sequence of binary values. An example of the output file is available `at the RaptorJIT project <https://github.com/raptorjit/raptorjit/blob/master/src/reusevm/lj_vm.S>`_.
* The generated VM code contains assembler routines for each LuaJIT bytecode, and also a number of other library and utility functions.
* The offsets of the byte code assembler routines are gathered and used to create the computed goto ``DISPATCH`` table. This table is stored alongside `LuaJIT global_State/lua_State structure in GG_State <https://github.com/LuaJIT/LuaJIT/blob/master/src/lj_dispatch.h>`_. The initialization of the dispatch table occurs in ``lj_dispatch_init()`` function in `lj_dispatch.c <https://github.com/LuaJIT/LuaJIT/blob/master/src/lj_dispatch.c>`_. The relevant code is shown below.
::
/* Initialize instruction dispatch table and hot counters. */
void lj_dispatch_init(GG_State *GG)
{
uint32_t i;
ASMFunction *disp = GG->dispatch;
for (i = 0; i < GG_LEN_SDISP; i++)
disp[GG_LEN_DDISP+i] = disp[i] = makeasmfunc(lj_bc_ofs[i]);
for (i = GG_LEN_SDISP; i < GG_LEN_DDISP; i++)
disp[i] = makeasmfunc(lj_bc_ofs[i]);
/* omitted code */
}
* Each generated bye-code assembly function does a fetch of the next bytecode instruction and then jumps to the assembly function for the next op code using the ``DISPATCH`` table.

@ -1,297 +0,0 @@
Design and Implementation Notes
===============================
The overall approach is:
* For each bytecode create an assembler routine
* Create a dispatch table with pointers to the assembler routines; the dispatch table is stored in the Lua global_State structure
but this could change in future
* Each assembler routine will (after completing its action) fetch the next bytecode instruction and jump to the next
assembler routine using the dispatch table (equivalent to computed goto)
* The assembler routines are **not** C functions - they are part of one whole program. Hence they make assumptions about
register usage which will be documented below. The VM as a whole will have a fixed set of register allocations so that most
important information is held in registers.
Implementation Considerations
-----------------------------
* The dispatch table is stored in global_State - it is not clear yet whether it is worth making a local stack copy of it when the
VM starts executing.
Why dynasm
----------
The implementation requires following key abilities that dynasm has:
* Obtain the offsets of the bytecode labels so that these can be gathered into a dispatch table.
* Use C code to calculate various structure offsets etc.
* Macros to create aliases for registers, and generate common sequences.
I am not sure whether this combination of features is available in other approaches such as using inline assembler in C code. I have briefly looked at:
* Inline assembly in gcc / clang - too ugly syntactically to work with
* Inline assembly in D - almost okay - no macros however so simple stuff like creating aliases for registers requires ugly mixin templates. The generated code appears to lack enough controls (such as disabling the frame pointer register, and ensuring correct unwind data on Win64). Also do not know how to get the offsets from generated code.
Using an assembler like yasm has the problem of computing offsets of C structures.
Issues with dynasm
------------------
On Windows 64-bit the generated code requires UNWIND information however the mechanism for this was in LuaJIT specific files (buildvm_peobj) and not fully reusable. I have modified this to de-couple from LuaJIT. This took some effort because LuaJIT's code
has numerous magic numbers with no explanation of what the code is doing. Not very helpful for anyone trying to work out what
the code is doing unless you already know what needs doing.
I wish dynasm could generate annotated assembly source file that is human readable. This would allow debuggers to display the
source code and would make debugging the assembly instructions much easier.
Register Allocations
--------------------
The VM will use a fixed set of registers mostly with some register usage varying across routines. The following table shows the
planned usage.
Nomenclature
* cs - callee saved, if we call a C function then after it returns we can rely on these registers
* v - volatile, these registers may be overridden by a called function so do not rely on them after function call
* `(n)` - used to pass arg n to function
+--------------------+------------------+------------------------------+------------------------------------------+
| Windows X64 reg | Linux X64 reg | Assignment | Notes |
+====================+==================+==============================+==========================================+
| rbx (cs) | rbx (cs) | PC | Pointer to next bytecode |
+--------------------+------------------+------------------------------+------------------------------------------+
| rbp (cs) | rbp (cs) | L | Pointer to lua_State |
+--------------------+------------------+------------------------------+------------------------------------------+
| rdi (cs) | rdi (v) (1) | | |
+--------------------+------------------+------------------------------+------------------------------------------+
| rsi (cs) | rsi (v) (2) | | |
+--------------------+------------------+------------------------------+------------------------------------------+
| rsp (cs) | rsp | | Stack pointer |
+--------------------+------------------+------------------------------+------------------------------------------+
| r12 (cs) | r12 (cs) | CI | CallInfo (Lua frame) |
+--------------------+------------------+------------------------------+------------------------------------------+
| r13 (cs) | r13 (cs) | LCL | Current function's LClosure |
+--------------------+------------------+------------------------------+------------------------------------------+
| r14 (cs) | r14 (cs) | DISPATCH | Ptr to Dispatch table |
+--------------------+------------------+------------------------------+------------------------------------------+
| r15 (cs) | r15 (cs) | KBASE | Ptr to constants table in Proto |
+--------------------+------------------+------------------------------+------------------------------------------+
| rax (v) | rax (v) | RCa = rax, RC = eax | Scratch - also eax used for |
| | | | the B,C portion of bytecode |
+--------------------+------------------+------------------------------+------------------------------------------+
| rcx (v) (1) | rcx (v) (4) | RAa = rcx, RA = ecx | Scratch - also ecx used for |
| | | | the value of A in bytecode |
+--------------------+------------------+------------------------------+------------------------------------------+
| rdx (v) (2) | rdx (v) (3) | RBa = rdx, OP = edx | Scratch - also edx used for |
| | | | the OpCode |
+--------------------+------------------+------------------------------+------------------------------------------+
| r8 (v) (3) | r8 (v) (5) | BASE | Pointer to Lua stack base |
+--------------------+------------------+------------------------------+------------------------------------------+
| r9 (v) (4) | r9 (v) (6) | TMP3 | Scratch |
+--------------------+------------------+------------------------------+------------------------------------------+
| r10 (v) | r10 (v | TMP1 | Scratch |
+--------------------+------------------+------------------------------+------------------------------------------+
| r11 (v) | r11 (v) | TMP2 | Scratch |
+--------------------+------------------+------------------------------+------------------------------------------+
Stack space
-----------
On Win64 every function gets a 32-byte shadow space for the 4 register arguments, which we can use. But we also need
to provide a shadow space for function calls inside the VM. Basically these 4 stack positions cancel out if we make use
of the slots provided by the caller.
VMBuilder
---------
The `VMBuilder <https://github.com/dibyendumajumdar/ravi/tree/master/vmbuilder/src>`_ is a tool that generates the code for the VM. It is a sub-project and the only component that needs to use dynasm.
To build the tool, you have to use CMake. Following steps are for Windows::
cd vmbuilder\src
mkdir build
cd build
cmake -G "Visual Studio 15 Win64" ..
Above will generate the Visual Studio project that you can open in VS2017. Do a BUILD, followed by INSTALL. The resulting buildvm.exe
will be installed under ``vmbuilber/bin``.
On Linux, the process is as follows::
cd vmbuilder/src
mkdir build
cd build
cmake ..
make
make install
Running VMBuilder on Windows
----------------------------
VMBuilder tool is run as follows on Windows::
cd vmbuilder\bin
buildvm -m peobj -o vm.obj
buildvm -m bcdef > ravi_bcdef.h
If you have LLVM installed you can obtain the assembly source as follows::
llvm-objdump -unwind-info -d -t vm.obj > vm.asm
Running VMBuilder on UNIX systems
---------------------------------
On Linux, the steps for unning ``buildvm`` are::
cd vmbuilder/bin
./buildvm -m elfasm -o vm.s
./buildvm -m bcdef > ravi_bcdef.h
Note that you should not have to run VMBuilder manually this way as the Ravi CMake build will do these steps anyway.
Files generated by VMBuilder
----------------------------
On Windows VMBuilder generates an object file. On Linux and Mac OSX it generates assembly source file.
The generated file is then linked with the main Ravi library.
Additionally a header file is generated named 'ravi_bcdef.h' - containing an array of offsets that can be used to obtain the
address of each assembly routine by adding the offset to the 'ravi_vm_asm_begin' symbol.
Current Issues
--------------
* Some additional work may be necessary to link the ASM routines when shared library builds are on - at least on Windows where
I noticed that the ASM functions were not properly being invoked. Have switched to static builds for now.
Exported Symbols
----------------
The main public symbols that are accessed externally are:
* ravi_vm_asm_begin - this is the start of the generated code, and all the assembly routines are at offets relative to the address of this symbol.
* ravi_luaV_interp - this is the entry VM point, equivalent to luaV_execute().
Setup of dispatch table
-----------------------
Currently this occurs in `lstate.c <https://github.com/dibyendumajumdar/ravi/blob/master/src/lstate.c>`_ in function ``dispatch_init()`` which is shown below::
#ifdef RAVI_USE_ASMVM
/* Initialize dispatch table used by the ASM VM */
static void dispatch_init(global_State *G) {
ASMFunction *disp = G->dispatch;
for (uint32_t i = 0; i < NUM_OPCODES; i++) {
/*
Following computes an offset for the assembly routine for the given OpCode.
The offset is relative to the global symbol ravi_vm_asm_begin that is
generated as part of the VMBuilder code generation. All the bytecode
routines are at some offset to this global symbol.
*/
/* NOTE: enabling ltests.h modifies the global_State and breaks the assumptions about
the location of the dispatch table */
disp[i] = makeasmfunc(ravi_bytecode_offsets[i]);
}
}
#endif
OpCode structure
----------------
The OpCode is stored in LuaJIT inspired format when the ASM VM is enabled. This is showns below::
+---+---+---+----+
| B | C | A | Op |
+---+---+---+----+
| Bx | A | Op |
+-------+---+----+
| Ax | Op |
+-----------+----+
Note that the bytecode decoding assumes above and will break if Lua style encoding is used.
Progress
--------
The only op codes implemented so far are:
* OP_RETURN (some scenarios to be tested, e.g. upvalues)
* OP_LOADK
* OP_MOVE
* OP_RAVI_FORPREP_IP and OP_RAVI_FORPREP_I1
* OP_RAVI_FORLOOP_I1 and OP_RAVI_FORLOOP_I1
Here is a `link to the generated assembly code on Windows X64 <https://github.com/dibyendumajumdar/ravi/blob/master/vmbuilder/asm/vm-win64.asm>`_.
The equivalent `Linux assembly code is <https://github.com/dibyendumajumdar/ravi/blob/master/vmbuilder/asm/vm-linux64.s>`_.
It seems hard to test and validate the assembly code. I have to step through the code instruction by instruction.
On Windows I debug in Visual Studio 2017.
On Linux I use Eclipse CDT to debug the code. I use the instruction step mode.
On Mac OSX I use Xcode.
I think it might be useful to create a test harness that mocks the Lua structures
and functions so that each bytecode instruction can be tested in isolation. This will need some work however, so not yet sure.
The other alternative is to check by running Lua scripts which is how we test Ravi normally.
Windows X64 Specifics
---------------------
On Windows the VMBuilder tool generates object code rather than an assembly source file. Win64 also requires some special data
for stack unwinding in case of exceptions. I believe even longjmps trigger this functionality.
The way we handle this now is by generating following in the object file::
Unwind info:
Function Table:
Start Address: ravi_vm_asm_begin
End Address: ravi_vm_asm_begin + 0x06a2
Unwind Info Address: .xdata
Version: 1
Flags: 0
Size of prolog: 0
Number of Codes: 9
No frame pointer used
Unwind Codes:
0x00: UOP_AllocSmall 40
0x00: UOP_PushNonVol R15
0x00: UOP_PushNonVol R14
0x00: UOP_PushNonVol R13
0x00: UOP_PushNonVol R12
0x00: UOP_PushNonVol RBX
0x00: UOP_PushNonVol RSI
0x00: UOP_PushNonVol RDI
0x00: UOP_PushNonVol RBP
Basically above tells Windows what the function epilogue (stack) looks like so that Windows can correctly restore the registers when
unwinding the stack. Note that the unwind information applies to the entire generated code and not a specific function. In particular
the assumption is that there any entry point in the code needs to have a prologue that is the exact inverse of the
epilogue described above.
Here is the function prologue::
ravi_luaV_interp:
651: 55 pushq %rbp
652: 57 pushq %rdi
653: 56 pushq %rsi
654: 53 pushq %rbx
655: 41 54 pushq %r12
657: 41 55 pushq %r13
659: 41 56 pushq %r14
65b: 41 57 pushq %r15
65d: 48 83 ec 28 subq $40, %rsp
And the epilogue::
ravi_vm_return:
691: 48 83 c4 28 addq $40, %rsp
695: 41 5f popq %r15
697: 41 5e popq %r14
699: 41 5d popq %r13
69b: 41 5c popq %r12
69d: 5b popq %rbx
69e: 5e popq %rsi
69f: 5f popq %rdi
6a0: 5d popq %rbp
6a1: c3 retq
As you can see the unwind information basically tells Windows what the epilogue is supposed to be, and where to find the saved
values of the registers.
Building Ravi With New ASM VM
-----------------------------
This is only for the brave who want to hack with the code.
To enable the new VM first build and install VMBuilder as described above.
Then build Ravi using the cmake flags ``-DSTATIC_BUILD=ON`` and ``-DASM_VM=ON`` enabled. Don't enable JIT.
Right now the ASM VM is exercised via the ``test_asmvm`` sub project. The ASM VM is only invoked in special cases, i.e. a function has small number of instructions and only contains supported instructions, and additionally as OP_CALL is not yet implemented, you can only call the new VM via the Lua C api (see `test_asmvm() in test_asmvm.c <https://github.com/dibyendumajumdar/ravi/blob/master/tests/test_asmvm.c>`_).

@ -1,456 +0,0 @@
/*
** DynASM ARM encoding engine.
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "arm"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC,
DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, DASM_IMMV8,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
static int dasm_imm12(unsigned int n)
{
int i;
for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30))
if (n <= 255) return (int)(n + (i << 8));
return -1;
}
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
case DASM_IMM16:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
if ((ins & 0x8000))
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
case DASM_IMMV8:
CK((n & 3) == 0, RANGE_I);
n >>= 2;
case DASM_IMML8:
case DASM_IMML12:
CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) :
(((-n)>>((ins>>5)&31)) == 0), RANGE_I);
b[pos++] = n;
break;
case DASM_IMM12:
CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMM12: case DASM_IMM16:
case DASM_IMML8: case DASM_IMML12: case DASM_IMMV8: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
break;
case DASM_REL_LG:
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4;
patchrel:
if ((ins & 0x800) == 0) {
CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL);
cp[-1] |= ((n >> 2) & 0x00ffffff);
} else if ((ins & 0x1000)) {
CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL);
goto patchimml8;
} else if ((ins & 0x2000) == 0) {
CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL);
goto patchimml;
} else {
CK((n & 3) == 0 && -1020 <= n && n <= 1020, RANGE_REL);
n >>= 2;
goto patchimml;
}
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
case DASM_IMM12:
cp[-1] |= dasm_imm12((unsigned int)n);
break;
case DASM_IMM16:
cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff);
break;
case DASM_IMML8: patchimml8:
cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) :
((-n & 0x0f) | ((-n & 0xf0) << 4));
break;
case DASM_IMML12: case DASM_IMMV8: patchimml:
cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load Diff

@ -1,518 +0,0 @@
/*
** DynASM ARM64 encoding engine.
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "arm64"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC,
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
static int dasm_imm12(unsigned int n)
{
if ((n >> 12) == 0)
return n;
else if ((n & 0xff000fff) == 0)
return (n >> 12) | 0x1000;
else
return -1;
}
static int dasm_ffs(unsigned long long x)
{
int n = -1;
while (x) { x >>= 1; n++; }
return n;
}
static int dasm_imm13(int lo, int hi)
{
int inv = 0, w = 64, s = 0xfff, xa, xb;
unsigned long long n = (((unsigned long long)hi) << 32) | (unsigned int)lo;
unsigned long long m = 1ULL, a, b, c;
if (n & 1) { n = ~n; inv = 1; }
a = n & -n; b = (n+a)&-(n+a); c = (n+a-b)&-(n+a-b);
xa = dasm_ffs(a); xb = dasm_ffs(b);
if (c) {
w = dasm_ffs(c) - xa;
if (w == 32) m = 0x0000000100000001UL;
else if (w == 16) m = 0x0001000100010001UL;
else if (w == 8) m = 0x0101010101010101UL;
else if (w == 4) m = 0x1111111111111111UL;
else if (w == 2) m = 0x5555555555555555UL;
else return -1;
s = (-2*w & 0x3f) - 1;
} else if (!a) {
return -1;
} else if (xb == -1) {
xb = 64;
}
if ((b-a) * m != n) return -1;
if (inv) {
return ((w - xb) << 6) | (s+w+xa-xb);
} else {
return ((w - xa) << 6) | (s+xb-xa);
}
return -1;
}
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
n >>= ((ins>>10)&31);
#ifdef DASM_CHECKS
if ((ins & 0x8000))
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
case DASM_IMM6:
CK((n >> 6) == 0, RANGE_I);
b[pos++] = n;
break;
case DASM_IMM12:
CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
b[pos++] = n;
break;
case DASM_IMM13W:
CK(dasm_imm13(n, n) != -1, RANGE_I);
b[pos++] = n;
break;
case DASM_IMM13X: {
int m = va_arg(ap, int);
CK(dasm_imm13(n, m) != -1, RANGE_I);
b[pos++] = n;
b[pos++] = m;
break;
}
case DASM_IMML: {
#ifdef DASM_CHECKS
int scale = (p[-2] >> 30);
CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ||
(unsigned int)(n+256) < 512, RANGE_I);
#endif
b[pos++] = n;
break;
}
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
case DASM_IMML: pos++; break;
case DASM_IMM13X: pos += 2; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
break;
case DASM_REL_LG:
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) + 4;
patchrel:
if (!(ins & 0xf800)) { /* B, BL */
CK((n & 3) == 0 && ((n+0x08000000) >> 28) == 0, RANGE_REL);
cp[-1] |= ((n >> 2) & 0x03ffffff);
} else if ((ins & 0x800)) { /* B.cond, CBZ, CBNZ, LDR* literal */
CK((n & 3) == 0 && ((n+0x00100000) >> 21) == 0, RANGE_REL);
cp[-1] |= ((n << 3) & 0x00ffffe0);
} else if ((ins & 0x3000) == 0x2000) { /* ADR */
CK(((n+0x00100000) >> 21) == 0, RANGE_REL);
cp[-1] |= ((n << 3) & 0x00ffffe0) | ((n & 3) << 29);
} else if ((ins & 0x3000) == 0x3000) { /* ADRP */
cp[-1] |= ((n >> 9) & 0x00ffffe0) | (((n >> 12) & 3) << 29);
} else if ((ins & 0x1000)) { /* TBZ, TBNZ */
CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL);
cp[-1] |= ((n << 3) & 0x0007ffe0);
}
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
case DASM_IMM6:
cp[-1] |= ((n&31) << 19) | ((n&32) << 26);
break;
case DASM_IMM12:
cp[-1] |= (dasm_imm12((unsigned int)n) << 10);
break;
case DASM_IMM13W:
cp[-1] |= (dasm_imm13(n, n) << 10);
break;
case DASM_IMM13X:
cp[-1] |= (dasm_imm13(n, *b++) << 10);
break;
case DASM_IMML: {
int scale = (p[-2] >> 30);
cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ?
((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
break;
}
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load Diff

@ -1,419 +0,0 @@
/*
** DynASM MIPS encoding engine.
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "mips"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMS,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM: case DASM_IMMS:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
#endif
n >>= ((ins>>10)&31);
#ifdef DASM_CHECKS
if (ins & 0x8000)
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMMS: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16) - 0xff00;
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1);
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
break;
case DASM_REL_LG:
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n);
if (ins & 2048)
n = n - (int)((char *)cp - base);
else
n = (n + (int)(size_t)base) & 0x0fffffff;
patchrel:
CK((n & 3) == 0 &&
((n + ((ins & 2048) ? 0x00020000 : 0)) >>
((ins & 2048) ? 18 : 28)) == 0, RANGE_REL);
cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff));
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMMS:
cp[-1] |= ((n>>3) & 4); n &= 0x1f;
/* fallthrough */
case DASM_IMM:
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load Diff

@ -1,12 +0,0 @@
------------------------------------------------------------------------------
-- DynASM MIPS64 module.
--
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
-- All the interesting stuff is there.
------------------------------------------------------------------------------
mips64 = true -- Using a global is an ugly, but effective solution.
return require("dasm_mips")

@ -1,419 +0,0 @@
/*
** DynASM PPC/PPC64 encoding engine.
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "ppc"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. */
enum {
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
/* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMSH,
DASM__MAX
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000
#define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned int *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
if (action >= DASM__MAX) {
ofs += 4;
} else {
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
switch (action) {
case DASM_STOP: goto stop;
case DASM_SECTION:
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl += 10; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
break;
case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC:
pl = D->pclabels + n; CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
}
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_IMM:
#ifdef DASM_CHECKS
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
#endif
n >>= ((ins>>10)&31);
#ifdef DASM_CHECKS
if (ins & 0x8000)
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
else
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
#endif
b[pos++] = n;
break;
case DASM_IMMSH:
CK((n >> 6) == 0, RANGE_I);
b[pos++] = n;
break;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: p++; break;
case DASM_REL_EXT: break;
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMMSH: pos++; break;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
#else
#define CK(x, st) ((void)0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
char *base = (char *)buffer;
unsigned int *cp = (unsigned int *)buffer;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
while (1) {
unsigned int ins = *p++;
unsigned int action = (ins >> 16);
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
switch (action) {
case DASM_STOP: case DASM_SECTION: goto stop;
case DASM_ESC: *cp++ = *p++; break;
case DASM_REL_EXT:
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1) - 4;
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
break;
case DASM_REL_LG:
CK(n >= 0, UNDEF_LG);
case DASM_REL_PC:
CK(n >= 0, UNDEF_PC);
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
patchrel:
CK((n & 3) == 0 &&
(((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >>
((ins & 2048) ? 16 : 26)) == 0, RANGE_REL);
cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc));
break;
case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break;
case DASM_LABEL_PC: break;
case DASM_IMM:
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
break;
case DASM_IMMSH:
cp[-1] |= (ins & 1) ? ((n&31)<<11)|((n&32)>>4) : ((n&31)<<6)|(n&32);
break;
default: *cp++ = ins; break;
}
}
stop: (void)0;
}
}
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
#undef CK
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load Diff

@ -1,83 +0,0 @@
/*
** DynASM encoding engine prototypes.
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#ifndef _DASM_PROTO_H
#define _DASM_PROTO_H
#include <stddef.h>
#include <stdarg.h>
#define DASM_IDENT "DynASM 1.4.0"
#define DASM_VERSION 10400 /* 1.4.0 */
#ifndef Dst_DECL
#define Dst_DECL dasm_State **Dst
#endif
#ifndef Dst_REF
#define Dst_REF (*Dst)
#endif
#ifndef DASM_FDEF
#define DASM_FDEF extern
#endif
#ifndef DASM_M_GROW
#define DASM_M_GROW(ctx, t, p, sz, need) \
do { \
size_t _sz = (sz), _need = (need); \
if (_sz < _need) { \
if (_sz < 16) _sz = 16; \
while (_sz < _need) _sz += _sz; \
(p) = (t *)realloc((p), _sz); \
if ((p) == NULL) exit(1); \
(sz) = _sz; \
} \
} while(0)
#endif
#ifndef DASM_M_FREE
#define DASM_M_FREE(ctx, p, sz) free(p)
#endif
/* Internal DynASM encoder state. */
typedef struct dasm_State dasm_State;
/* Initialize and free DynASM state. */
DASM_FDEF void dasm_init(Dst_DECL, int maxsection);
DASM_FDEF void dasm_free(Dst_DECL);
/* Setup global array. Must be called before dasm_setup(). */
DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl);
/* Grow PC label array. Can be called after dasm_setup(), too. */
DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc);
/* Setup encoder. */
DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist);
/* Feed encoder with actions. Calls are generated by pre-processor. */
DASM_FDEF void dasm_put(Dst_DECL, int start, ...);
/* Link sections and return the resulting size. */
DASM_FDEF int dasm_link(Dst_DECL, size_t *szp);
/* Encode sections into buffer. */
DASM_FDEF int dasm_encode(Dst_DECL, void *buffer);
/* Get PC label offset. */
DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc);
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch);
#else
#define dasm_checkstep(a, b) 0
#endif
#endif /* _DASM_PROTO_H */

@ -1,12 +0,0 @@
------------------------------------------------------------------------------
-- DynASM x64 module.
--
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------
-- This module just sets 64 bit mode for the combined x86/x64 module.
-- All the interesting stuff is there.
------------------------------------------------------------------------------
x64 = true -- Using a global is an ugly, but effective solution.
return require("dasm_x86")

@ -1,499 +0,0 @@
/*
** DynASM x86 encoding engine.
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define DASM_ARCH "x86"
#ifndef DASM_EXTERN
#define DASM_EXTERN(a,b,c,d) 0
#endif
/* Action definitions. DASM_STOP must be 255. */
enum {
DASM_DISP = 233,
DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB,
DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC,
DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN,
DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP
};
/* Maximum number of section buffer positions for a single dasm_put() call. */
#define DASM_MAXSECPOS 25
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
#define DASM_S_OK 0x00000000
#define DASM_S_NOMEM 0x01000000
#define DASM_S_PHASE 0x02000000
#define DASM_S_MATCH_SEC 0x03000000
#define DASM_S_RANGE_I 0x11000000
#define DASM_S_RANGE_SEC 0x12000000
#define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_VREG 0x15000000
#define DASM_S_UNDEF_L 0x21000000
#define DASM_S_UNDEF_PC 0x22000000
/* Macros to convert positions (8 bit section + 24 bit index). */
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
#define DASM_SEC2POS(sec) ((sec)<<24)
#define DASM_POS2SEC(pos) ((pos)>>24)
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
/* Action list type. */
typedef const unsigned char *dasm_ActList;
/* Per-section structure. */
typedef struct dasm_Section {
int *rbuf; /* Biased buffer pointer (negative section bias). */
int *buf; /* True buffer pointer. */
size_t bsize; /* Buffer size in bytes. */
int pos; /* Biased buffer position. */
int epos; /* End of biased buffer position - max single put. */
int ofs; /* Byte offset into section. */
} dasm_Section;
/* Core structure holding the DynASM encoding state. */
struct dasm_State {
size_t psize; /* Allocated size of this structure. */
dasm_ActList actionlist; /* Current actionlist pointer. */
int *lglabels; /* Local/global chain/pos ptrs. */
size_t lgsize;
int *pclabels; /* PC label chains/pos ptrs. */
size_t pcsize;
void **globals; /* Array of globals (bias -10). */
dasm_Section *section; /* Pointer to active section. */
size_t codesize; /* Total size of all code sections. */
int maxsection; /* 0 <= sectionidx < maxsection. */
int status; /* Status code. */
dasm_Section sections[1]; /* All sections. Alloc-extended. */
};
/* The size of the core structure depends on the max. number of sections. */
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
/* Initialize DynASM state. */
void dasm_init(Dst_DECL, int maxsection)
{
dasm_State *D;
size_t psz = 0;
int i;
Dst_REF = NULL;
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
D = Dst_REF;
D->psize = psz;
D->lglabels = NULL;
D->lgsize = 0;
D->pclabels = NULL;
D->pcsize = 0;
D->globals = NULL;
D->maxsection = maxsection;
for (i = 0; i < maxsection; i++) {
D->sections[i].buf = NULL; /* Need this for pass3. */
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
D->sections[i].bsize = 0;
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
}
}
/* Free DynASM state. */
void dasm_free(Dst_DECL)
{
dasm_State *D = Dst_REF;
int i;
for (i = 0; i < D->maxsection; i++)
if (D->sections[i].buf)
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
DASM_M_FREE(Dst, D, D->psize);
}
/* Setup global label array. Must be called before dasm_setup(). */
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
{
dasm_State *D = Dst_REF;
D->globals = gl - 10; /* Negative bias to compensate for locals. */
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
}
/* Grow PC label array. Can be called after dasm_setup(), too. */
void dasm_growpc(Dst_DECL, unsigned int maxpc)
{
dasm_State *D = Dst_REF;
size_t osz = D->pcsize;
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
}
/* Setup encoder. */
void dasm_setup(Dst_DECL, const void *actionlist)
{
dasm_State *D = Dst_REF;
int i;
D->actionlist = (dasm_ActList)actionlist;
D->status = DASM_S_OK;
D->section = &D->sections[0];
memset((void *)D->lglabels, 0, D->lgsize);
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
for (i = 0; i < D->maxsection; i++) {
D->sections[i].pos = DASM_SEC2POS(i);
D->sections[i].ofs = 0;
}
}
#ifdef DASM_CHECKS
#define CK(x, st) \
do { if (!(x)) { \
D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
#define CKPL(kind, st) \
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
#else
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
#endif
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
void dasm_put(Dst_DECL, int start, ...)
{
va_list ap;
dasm_State *D = Dst_REF;
dasm_ActList p = D->actionlist + start;
dasm_Section *sec = D->section;
int pos = sec->pos, ofs = sec->ofs, mrm = -1;
int *b;
if (pos >= sec->epos) {
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
}
b = sec->rbuf;
b[pos++] = start;
va_start(ap, start);
while (1) {
int action = *p++;
if (action < DASM_DISP) {
ofs++;
} else if (action <= DASM_REL_A) {
int n = va_arg(ap, int);
b[pos++] = n;
switch (action) {
case DASM_DISP:
if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; }
case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob;
case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
case DASM_IMM_D: ofs += 4; break;
case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break;
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob;
case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
case DASM_SPACE: p++; ofs += n; break;
case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG);
if (*p < 0x40 && p[1] == DASM_DISP) mrm = n;
if (*p < 0x20 && (n&7) == 4) ofs++;
switch ((*p++ >> 3) & 3) {
case 3: n |= b[pos-3];
case 2: n |= b[pos-2];
case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; }
}
continue;
}
mrm = -1;
} else {
int *pl, n;
switch (action) {
case DASM_REL_LG:
case DASM_IMM_LG:
n = *p++; pl = D->lglabels + n;
/* Bkwd rel or global. */
if (n <= 246) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
pl -= 246; n = *pl;
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
goto linkrel;
case DASM_REL_PC:
case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
putrel:
n = *pl;
if (n < 0) { /* Label exists. Get label pos and store it. */
b[pos] = -n;
} else {
linkrel:
b[pos] = n; /* Else link to rel chain, anchored at label. */
*pl = pos;
}
pos++;
ofs += 4; /* Maximum offset needed. */
if (action == DASM_REL_LG || action == DASM_REL_PC)
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
putlabel:
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; }
*pl = -pos; /* Label exists now. */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_ALIGN:
ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */
b[pos++] = ofs; /* Store pass1 offset estimate. */
break;
case DASM_EXTERN: p += 2; ofs += 4; break;
case DASM_ESC: p++; ofs++; break;
case DASM_MARK: mrm = p[-2]; break;
case DASM_SECTION:
n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n];
case DASM_STOP: goto stop;
}
}
}
stop:
va_end(ap);
sec->pos = pos;
sec->ofs = ofs;
}
#undef CK
/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */
int dasm_link(Dst_DECL, size_t *szp)
{
dasm_State *D = Dst_REF;
int secnum;
int ofs = 0;
#ifdef DASM_CHECKS
*szp = 0;
if (D->status != DASM_S_OK) return D->status;
{
int pc;
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
}
#endif
{ /* Handle globals not defined in this translation unit. */
int idx;
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
}
}
/* Combine all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->rbuf;
int pos = DASM_SEC2POS(secnum);
int lastpos = sec->pos;
while (pos != lastpos) {
dasm_ActList p = D->actionlist + b[pos++];
while (1) {
int op, action = *p++;
switch (action) {
case DASM_REL_LG: p++; op = p[-3]; goto rel_pc;
case DASM_REL_PC: op = p[-2]; rel_pc: {
int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
if (shrink) { /* Shrinkable branch opcode? */
int lofs, lpos = b[pos];
if (lpos < 0) goto noshrink; /* Ext global? */
lofs = *DASM_POS2PTR(D, lpos);
if (lpos > pos) { /* Fwd label: add cumulative section offsets. */
int i;
for (i = secnum; i < DASM_POS2SEC(lpos); i++)
lofs += D->sections[i].ofs;
} else {
lofs -= ofs; /* Bkwd label: unfix offset. */
}
lofs -= b[pos+1]; /* Short branch ok? */
if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */
else { noshrink: shrink = 0; } /* No, cannot shrink op. */
}
b[pos+1] = shrink;
pos += 2;
break;
}
case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++;
case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W:
case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB:
case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break;
case DASM_LABEL_LG: p++;
case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
case DASM_EXTERN: p += 2; break;
case DASM_ESC: p++; break;
case DASM_MARK: break;
case DASM_SECTION: case DASM_STOP: goto stop;
}
}
stop: (void)0;
}
ofs += sec->ofs; /* Next section starts right after current section. */
}
D->codesize = ofs; /* Total size of all code sections */
*szp = ofs;
return DASM_S_OK;
}
#define dasmb(x) *cp++ = (unsigned char)(x)
#ifndef DASM_ALIGNED_WRITES
#define dasmw(x) \
do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
#define dasmd(x) \
do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
#else
#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
#endif
/* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer)
{
dasm_State *D = Dst_REF;
unsigned char *base = (unsigned char *)buffer;
unsigned char *cp = base;
int secnum;
/* Encode all code sections. No support for data sections (yet). */
for (secnum = 0; secnum < D->maxsection; secnum++) {
dasm_Section *sec = D->sections + secnum;
int *b = sec->buf;
int *endb = sec->rbuf + sec->pos;
while (b != endb) {
dasm_ActList p = D->actionlist + *b++;
unsigned char *mark = NULL;
while (1) {
int action = *p++;
int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0;
switch (action) {
case DASM_DISP: if (!mark) mark = cp; {
unsigned char *mm = mark;
if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL;
if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7;
if (mrm != 5) { mm[-1] -= 0x80; break; } }
if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40;
}
case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break;
case DASM_IMM_DB: if (((n+128)&-256) == 0) {
db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
} else mark = NULL;
case DASM_IMM_D: wd: dasmd(n); break;
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
case DASM_IMM_W: dasmw(n); break;
case DASM_VREG: {
int t = *p++;
unsigned char *ex = cp - (t&7);
if ((n & 8) && t < 0xa0) {
if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6);
n &= 7;
} else if (n & 0x10) {
if (*ex & 0x80) {
*ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2;
}
while (++ex < cp) ex[-1] = *ex;
if (mark) mark--;
cp--;
n &= 7;
}
if (t >= 0xc0) n <<= 4;
else if (t >= 0x40) n <<= 3;
else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; }
cp[-1] ^= n;
break;
}
case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
b++; n = (int)(ptrdiff_t)D->globals[-n];
case DASM_REL_A: rel_a:
n -= (unsigned int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
case DASM_REL_PC: rel_pc: {
int shrink = *b++;
int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; }
n = *pb - ((int)(cp-base) + 4-shrink);
if (shrink == 0) goto wd;
if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb;
goto wb;
}
case DASM_IMM_LG:
p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; }
case DASM_IMM_PC: {
int *pb = DASM_POS2PTR(D, n);
n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base);
goto wd;
}
case DASM_LABEL_LG: {
int idx = *p++;
if (idx >= 10)
D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n));
break;
}
case DASM_LABEL_PC: case DASM_SETLABEL: break;
case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; }
case DASM_ALIGN:
n = *p++;
while (((cp-base) & n)) *cp++ = 0x90; /* nop */
break;
case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd;
case DASM_MARK: mark = cp; break;
case DASM_ESC: action = *p++;
default: *cp++ = action; break;
case DASM_SECTION: case DASM_STOP: goto stop;
}
}
stop: (void)0;
}
}
if (base + D->codesize != cp) /* Check for phase errors. */
return DASM_S_PHASE;
return DASM_S_OK;
}
/* Get PC label offset. */
int dasm_getpclabel(Dst_DECL, unsigned int pc)
{
dasm_State *D = Dst_REF;
if (pc*sizeof(int) < D->pcsize) {
int pos = D->pclabels[pc];
if (pos < 0) return *DASM_POS2PTR(D, -pos);
if (pos > 0) return -1; /* Undefined. */
}
return -2; /* Unused or out of range. */
}
#ifdef DASM_CHECKS
/* Optional sanity checker to call between isolated encoding steps. */
int dasm_checkstep(Dst_DECL, int secmatch)
{
dasm_State *D = Dst_REF;
if (D->status == DASM_S_OK) {
int i;
for (i = 1; i <= 9; i++) {
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; }
D->lglabels[i] = 0;
}
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
D->section != &D->sections[secmatch])
D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
return D->status;
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,67 +0,0 @@
# This CMake script is based on the LuaJIT one created by:
# Copyright (C) 2007-2013 LuaDist.
# Created by Peter Drahoš
# Redistribution and use of this file is allowed according to the terms of the MIT license.
# For details see the COPYRIGHT file distributed with LuaDist.
# Please note that the package source code is licensed under its own license.
project ( vmbuilder C )
cmake_minimum_required ( VERSION 2.8 )
set( RAVI_INCDIR ${CMAKE_CURRENT_SOURCE_DIR}/../../include )
set( DASM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../dynasm )
set( BINDIR ${CMAKE_CURRENT_SOURCE_DIR}/../bin )
set( SRCDIR ${CMAKE_CURRENT_SOURCE_DIR} )
# Dynasm
set ( DASM ${DASM_DIR}/dynasm.lua )
set ( DASM_T ${CMAKE_CURRENT_SOURCE_DIR}/buildvm_arch.h )
set ( DASM_DASC ${CMAKE_CURRENT_SOURCE_DIR}/vm_x64.dasc )
if ( APPLE )
list ( APPEND LIBS m )
elseif ( NOT WIN32 )
list ( APPEND LIBS m )
endif ()
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
# Build minilua
add_executable ( minilua minilua.c )
target_link_libraries ( minilua ${LIBS} )
include_directories(${RAVI_INCDIR})
include_directories(${DASM_DIR})
# Windows is ... special
if ( WIN32 )
list ( APPEND DASM_FLAGS -D WIN )
endif ()
list ( APPEND DASM_FLAGS -D P64 )
# Generate buildvm arch header
add_custom_command(OUTPUT ${DASM_T}
COMMAND minilua ${DASM} -MF ${DASM_FLAGS} -o ${DASM_T} ${DASM_DASC}
DEPENDS minilua ${DASM_DASC}
)
set(HEADERS
${RAVI_INCDIR}/ravi_arch.h
${RAVI_INCDIR}/ravi_def.h
${DASM_DIR}/dasm_proto.h
${DASM_DIR}/dasm_x86.h)
set(SRCS
${SRCDIR}/buildvm.c
${SRCDIR}/buildvm_asm.c
${SRCDIR}/buildvm_peobj.c
)
# Buildvm
add_executable ( buildvm ${SRCS} ${HEADERS} ${DASM_T} )
install( TARGETS buildvm
DESTINATION ${BINDIR} )

@ -1,550 +0,0 @@
/*
** LuaJIT VM builder.
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
**
** This is a tool to build the hand-tuned assembler code required for
** LuaJIT's bytecode interpreter. It supports a variety of output formats
** to feed different toolchains (see usage() below).
**
** This tool is not particularly optimized because it's only used while
** _building_ LuaJIT. There's no point in distributing or installing it.
** Only the object code generated by this tool is linked into LuaJIT.
**
** Caveat: some memory is not free'd, error handling is lazy.
** It's a one-shot tool -- any effort fixing this would be wasted.
*/
#define LUA_CORE
#include "lprefix.h"
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lvm.h"
#include "ravi_profile.h"
#include "buildvm.h"
#if defined(_WIN32)
#include <fcntl.h>
#include <io.h>
#endif
/* ------------------------------------------------------------------------ */
/* DynASM glue definitions. */
#define Dst ctx
#define Dst_DECL BuildCtx *ctx
#define Dst_REF (ctx->D)
#define DASM_CHECKS 1
#include "../dynasm/dasm_proto.h"
/* Glue macros for DynASM. */
static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type);
#define DASM_EXTERN(ctx, addr, idx, type) collect_reloc(ctx, addr, idx, type)
/* ------------------------------------------------------------------------ */
/* Avoid trouble if cross-compiling for an x86 target. Speed doesn't matter. */
#define DASM_ALIGNED_WRITES 1
/* Embed architecture-specific DynASM encoder. */
#if RAVI_TARGET_X86ORX64
#include "../dynasm/dasm_x86.h"
#elif RAVI_TARGET_ARM
#include "../dynasm/dasm_arm.h"
#elif RAVI_TARGET_ARM64
#include "../dynasm/dasm_arm64.h"
#elif RAVI_TARGET_PPC
#include "../dynasm/dasm_ppc.h"
#elif RAVI_TARGET_MIPS
#include "../dynasm/dasm_mips.h"
#else
#error "No support for this architecture (yet)"
#endif
/* Embed generated architecture-specific backend. */
#include "buildvm_arch.h"
/* ------------------------------------------------------------------------ */
void owrite(BuildCtx *ctx, const void *ptr, size_t sz) {
if (fwrite(ptr, 1, sz, ctx->fp) != sz) {
fprintf(stderr, "Error: cannot write to output file: %s\n",
strerror(errno));
exit(1);
}
}
/* ------------------------------------------------------------------------ */
/* Emit code as raw bytes. Only used for DynASM debugging. */
static void emit_raw(BuildCtx *ctx) { owrite(ctx, ctx->code, ctx->CodeSize); }
/* -- Build machine code -------------------------------------------------- */
static const char *sym_decorate(BuildCtx *ctx, const char *prefix,
const char *suffix) {
char name[256];
char *p;
#if RAVI_64
const char *symprefix = ctx->mode == BUILD_machasm ? "_" : "";
#else
const char *symprefix = ctx->mode != BUILD_elfasm ? "_" : "";
#endif
sprintf(name, "%s%s%s", symprefix, prefix, suffix);
p = strchr(name, '@');
if (p) {
#if RAVI_TARGET_X86ORX64
if (!RAVI_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj))
name[0] = name[1] == 'R' ? '_' : '@'; /* Just for _RtlUnwind@16. */
else
*p = '\0';
#else
*p = '\0';
#endif
}
p = (char *)malloc(strlen(name) + 1); /* MSVC doesn't like strdup. */
strcpy(p, name);
return p;
}
#define NRELOCSYM (sizeof(extnames) / sizeof(extnames[0]) - 1)
static int relocmap[NRELOCSYM + 1]; // Dibyendu: add +1 to allow no extnames
/*
Collect external relocations
addr is the address of the external symbol
idx is offset into ExportedSymbolNames as per dynasm unofficial docs
type = 0 means absolute address, type = 1 means relative address
*/
static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type) {
if (ctx->RelocSize >= BUILD_MAX_RELOC) {
fprintf(stderr, "Error: too many relocations, increase BUILD_MAX_RELOC.\n");
exit(1);
}
if (relocmap[idx] < 0) {
relocmap[idx] = ctx->nrelocsym;
ctx->RelocatableSymbolNames[ctx->nrelocsym] = sym_decorate(ctx, "", extnames[idx]);
ctx->nrelocsym++;
}
ctx->Reloc[ctx->RelocSize].RelativeOffset = (int32_t)(addr - ctx->code);
ctx->Reloc[ctx->RelocSize].sym = relocmap[idx];
ctx->Reloc[ctx->RelocSize].type = type;
ctx->RelocSize++;
return 0; /* Encode symbol offset of 0. */
}
/* Naive insertion sort. Performance doesn't matter here. */
static void sym_insert(BuildCtx *ctx, int32_t ofs, const char *prefix,
const char *suffix) {
ptrdiff_t i = ctx->NumberOfSymbols++;
while (i > 0) {
if (ctx->AllSymbols[i - 1].ofs <= ofs) break;
ctx->AllSymbols[i] = ctx->AllSymbols[i - 1];
i--;
}
ctx->AllSymbols[i].ofs = ofs;
ctx->AllSymbols[i].name = sym_decorate(ctx, prefix, suffix);
}
/* Build the machine code. */
static int build_code(BuildCtx *ctx) {
int status;
int i;
/* Initialize DynASM structures. */
ctx->NumberOfExportedSymbols = GLOB__MAX;
ctx->ExportedSymbols =
(void **)malloc(ctx->NumberOfExportedSymbols * sizeof(void *));
memset(ctx->ExportedSymbols, 0,
ctx->NumberOfExportedSymbols * sizeof(void *));
ctx->RelocSize = 0;
ctx->ExportedSymbolNames = globnames;
ctx->ImportedSymbolNames = extnames;
ctx->RelocatableSymbolNames = (const char **)malloc(NRELOCSYM * sizeof(const char *));
ctx->nrelocsym = 0;
for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1;
ctx->dasm_ident = DASM_IDENT;
ctx->dasm_arch = DASM_ARCH;
dasm_init(Dst, DASM_MAXSECTION);
dasm_setupglobal(Dst, ctx->ExportedSymbols, ctx->NumberOfExportedSymbols);
dasm_setup(Dst, build_actionlist);
/* Call arch-specific backend to emit the code. */
ctx->SizeofDispatchTable = build_backend(ctx);
/* Finalize the code. */
(void)dasm_checkstep(Dst, -1);
if ((status = dasm_link(Dst, &ctx->CodeSize))) return status;
ctx->code = (uint8_t *)malloc(ctx->CodeSize);
if ((status = dasm_encode(Dst, (void *)ctx->code))) return status;
/* Allocate symbol table and bytecode offsets. */
ctx->StartSymbol = sym_decorate(ctx, "", LABEL_PREFIX "vm_asm_begin");
ctx->AllSymbols = (BuildSym *)malloc(
(ctx->SizeofDispatchTable + ctx->NumberOfExportedSymbols + 1) *
sizeof(BuildSym)); // Presumably +1 is for a terminating NULL
ctx->NumberOfSymbols = 0;
ctx->DispatchTableOffsets =
(int32_t *)malloc(ctx->SizeofDispatchTable * sizeof(int32_t));
/* Collect the opcodes (PC labels). */
for (i = 0; i < ctx->SizeofDispatchTable; i++) {
int32_t ofs = dasm_getpclabel(Dst, i);
if (ofs < 0) return 0x22000000 | i;
ctx->DispatchTableOffsets[i] = ofs;
sym_insert(ctx, ofs, LABEL_PREFIX_BC, luaP_opnames[i]);
}
/* Collect the globals (named labels). */
for (i = 0; i < ctx->NumberOfExportedSymbols; i++) {
const char *gl = globnames[i];
int len = (int)strlen(gl);
if (!ctx->ExportedSymbols[i]) {
fprintf(stderr, "Error: undefined global %s\n", gl);
exit(2);
}
/* Skip the _Z symbols. */
if (!(len >= 2 && gl[len - 2] == '_' && gl[len - 1] == 'Z'))
// Enter the relative offset of the exported symbol, relative to the start
// of the code
sym_insert(ctx,
(int32_t)((uint8_t *)(ctx->ExportedSymbols[i]) - ctx->code),
LABEL_PREFIX, globnames[i]);
}
/* Close the address range. */
sym_insert(ctx, (int32_t)ctx->CodeSize, "", "");
ctx->NumberOfSymbols--;
dasm_free(Dst);
return 0;
}
static const char *lower(char *buf, const char *s) {
char *p = buf;
while (*s) {
*p++ = (*s >= 'A' && *s <= 'Z') ? *s + 0x20 : *s;
s++;
}
*p = '\0';
return buf;
}
/* Emit C source code for bytecode-related definitions. */
static void emit_bcdef(BuildCtx *ctx) {
int i;
fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n");
fprintf(ctx->fp, "/* ravi_bytecode_offsets contains offsets of OpCode implementations */\n");
/* Start of the ASM code. */
fprintf(ctx->fp, "#include <stdint.h>\n\n");
fprintf(ctx->fp, "extern char ravi_vm_asm_begin[];\n\n");
fprintf(ctx->fp, "/* Bytecode offsets are relative to ravi_vm_asm_begin. */\n");
fprintf(ctx->fp, "/* Internal assembler functions. Never call these directly from C. */\n");
fprintf(ctx->fp, "typedef void (*ASMFunction)(void);\n\n");
fprintf(ctx->fp, "#define makeasmfunc(ofs) ((ASMFunction)(ravi_vm_asm_begin + (ofs)))\n\n");
fprintf(ctx->fp, "static const uint16_t ravi_bytecode_offsets[] = {\n");
for (i = 0; i < ctx->SizeofDispatchTable; i++) {
if (i != 0) fprintf(ctx->fp, ",\n");
fprintf(ctx->fp, "%d", ctx->DispatchTableOffsets[i]);
}
fprintf(ctx->fp, "\n};\n");
}
/* -- Argument parsing ---------------------------------------------------- */
/* Build mode names. */
static const char *const modenames[] = {
#define BUILDNAME(name) #name,
BUILDDEF(BUILDNAME)
#undef BUILDNAME
NULL};
#define LUAJIT_VERSION "Ravi"
#define LUAJIT_COPYRIGHT "Based on LuaJIT 2.1.0-beta3, Copyright (C) 2005-2017 Mike Pall"
#define LUAJIT_URL "http://luajit.org/"
/* Print usage information and exit. */
static void usage(void) {
int i;
fprintf(stderr, LUAJIT_VERSION " VM builder.\n");
fprintf(stderr, LUAJIT_COPYRIGHT ", " LUAJIT_URL "\n");
fprintf(stderr, "Target architecture: " RAVI_ARCH_NAME "\n\n");
fprintf(stderr, "Usage: buildvm -m mode [-o outfile] [infiles...]\n\n");
fprintf(stderr, "Available modes:\n");
for (i = 0; i < BUILD__MAX; i++) fprintf(stderr, " %s\n", modenames[i]);
exit(1);
}
/* Parse the output mode name. */
static BuildMode parsemode(const char *mode) {
int i;
for (i = 0; modenames[i]; i++)
if (!strcmp(mode, modenames[i])) return (BuildMode)i;
usage();
return (BuildMode)-1;
}
/* Parse arguments. */
static void parseargs(BuildCtx *ctx, char **argv) {
const char *a;
int i;
ctx->mode = (BuildMode)-1;
ctx->outname = "-";
for (i = 1; (a = argv[i]) != NULL; i++) {
if (a[0] != '-') break;
switch (a[1]) {
case '-':
if (a[2]) goto err;
i++;
goto ok;
case '\0': goto ok;
case 'm':
i++;
if (a[2] || argv[i] == NULL) goto err;
ctx->mode = parsemode(argv[i]);
break;
case 'o':
i++;
if (a[2] || argv[i] == NULL) goto err;
ctx->outname = argv[i];
break;
default:
err:
usage();
break;
}
}
ok:
ctx->args = argv + i;
if (ctx->mode == (BuildMode)-1) goto err;
}
int main(int argc, char **argv) {
BuildCtx ctx_;
BuildCtx *ctx = &ctx_;
int status, binmode;
if (sizeof(void *) != 4 * RAVI_32 + 8 * RAVI_64) {
fprintf(stderr, "Error: pointer size mismatch in cross-build.\n");
fprintf(stderr, "Try: make HOST_CC=\"gcc -m32\" CROSS=...\n\n");
return 1;
}
UNUSED(argc);
parseargs(ctx, argv);
if ((status = build_code(ctx))) {
fprintf(stderr, "Error: DASM error %08x\n", status);
return 1;
}
switch (ctx->mode) {
case BUILD_peobj:
case BUILD_raw: binmode = 1; break;
default: binmode = 0; break;
}
if (ctx->outname[0] == '-' && ctx->outname[1] == '\0') {
ctx->fp = stdout;
#if defined(_WIN32)
if (binmode) _setmode(_fileno(stdout), _O_BINARY); /* Yuck. */
#endif
}
else if (!(ctx->fp = fopen(ctx->outname, binmode ? "wb" : "w"))) {
fprintf(stderr, "Error: cannot open output file '%s': %s\n", ctx->outname,
strerror(errno));
exit(1);
}
switch (ctx->mode) {
case BUILD_elfasm:
case BUILD_coffasm:
case BUILD_machasm:
emit_asm(ctx);
// emit_asm_debug(ctx);
break;
case BUILD_peobj: emit_peobj(ctx); break;
case BUILD_raw: emit_raw(ctx); break;
case BUILD_bcdef: emit_bcdef(ctx); break;
default: break;
}
fflush(ctx->fp);
if (ferror(ctx->fp)) {
fprintf(stderr, "Error: cannot write to output file: %s\n",
strerror(errno));
exit(1);
}
fclose(ctx->fp);
return 0;
}
// FIXME this is a copy of the array from lopcodes.c
LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES + 1] =
{
"MOVE",
"LOADK",
"LOADKX",
"LOADBOOL",
"LOADNIL",
"GETUPVAL",
"GETTABUP",
"GETTABLE",
"SETTABUP",
"SETUPVAL",
"SETTABLE",
"NEWTABLE",
"SELF",
"ADD",
"SUB",
"MUL",
"MOD",
"POW",
"DIV",
"IDIV",
"BAND",
"BOR",
"BXOR",
"SHL",
"SHR",
"UNM",
"BNOT",
"NOT",
"LEN",
"CONCAT",
"JMP",
"EQ",
"LT",
"LE",
"TEST",
"TESTSET",
"CALL",
"TAILCALL",
"RETURN",
"FORLOOP",
"FORPREP",
"TFORCALL",
"TFORLOOP",
"SETLIST",
"CLOSURE",
"VARARG",
"EXTRAARG",
"NEW_IARRAY", /* A R(A) := array of int */
"NEW_FARRAY", /* A R(A) := array of float */
"LOADIZ", /* A R(A) := tointeger(0) */
"LOADFZ", /* A R(A) := tonumber(0) */
"UNMF", /* A B R(A) := -R(B) floating point */
"UNMI", /* A B R(A) := -R(B) integer */
"ADDFF", /* A B C R(A) := RK(B) + RK(C) */
"ADDFI", /* A B C R(A) := RK(B) + RK(C) */
"ADDII", /* A B C R(A) := RK(B) + RK(C) */
"SUBFF", /* A B C R(A) := RK(B) - RK(C) */
"SUBFI", /* A B C R(A) := RK(B) - RK(C) */
"SUBIF", /* A B C R(A) := RK(B) - RK(C) */
"SUBII", /* A B C R(A) := RK(B) - RK(C) */
"MULFF", /* A B C R(A) := RK(B) * RK(C) */
"MULFI", /* A B C R(A) := RK(B) * RK(C) */
"MULII", /* A B C R(A) := RK(B) * RK(C) */
"DIVFF", /* A B C R(A) := RK(B) / RK(C) */
"DIVFI", /* A B C R(A) := RK(B) / RK(C) */
"DIVIF", /* A B C R(A) := RK(B) / RK(C) */
"DIVII", /* A B C R(A) := RK(B) / RK(C) */
"TOINT", /* A R(A) := toint(R(A)) */
"TOFLT", /* A R(A) := tofloat(R(A)) */
"TOIARRAY", /* A R(A) := to_arrayi(R(A)) */
"TOFARRAY", /* A R(A) := to_arrayf(R(A)) */
"TOTAB", /* A R(A) := to_table(R(A)) */
"TOSTRING",
"TOCLOSURE",
"TOTYPE",
"MOVEI", /* A B R(A) := R(B) */
"MOVEF", /* A B R(A) := R(B) */
"MOVEIARRAY", /* A B R(A) := R(B), check R(B) is array of int */
"MOVEFARRAY", /* A B R(A) := R(B), check R(B) is array of floats */
"MOVETAB", /* A B R(A) := R(B), check R(B) is a table */
"IARRAY_GET", /* A B C R(A) := R(B)[RK(C)] where R(B) is array of
integers and RK(C) is int */
"FARRAY_GET", /* A B C R(A) := R(B)[RK(C)] where R(B) is array of
floats and RK(C) is int */
"IARRAY_SET", /* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int,
R(A) is array of ints, and RK(C) is an int */
"FARRAY_SET", /* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int,
R(A) is array of floats, and RK(C) is an float */
"IARRAY_SETI", /* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int,
R(A) is array of ints, and RK(C) is an int */
"FARRAY_SETF", /* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int,
R(A) is array of floats, and RK(C) is an float */
"FORLOOP_IP",
"FORLOOP_I1",
"FORPREP_IP",
"FORPREP_I1",
"SETUPVALI", /* A B UpValue[B] := tointeger(R(A)) */
"SETUPVALF", /* A B UpValue[B] := tonumber(R(A)) */
"SETUPVAL_IARRAY", /* A B UpValue[B] := toarrayint(R(A)) */
"SETUPVAL_FARRAY", /* A B UpValue[B] := toarrayflt(R(A)) */
"SETUPVALT", /* A B UpValue[B] := to_table(R(A)) */
"BAND_II", /* A B C R(A) := RK(B) & RK(C) */
"BOR_II", /* A B C R(A) := RK(B) | RK(C) */
"BXOR_II", /* A B C R(A) := RK(B) ~ RK(C) */
"SHL_II", /* A B C R(A) := RK(B) << RK(C) */
"SHR_II", /* A B C R(A) := RK(B) >> RK(C) */
"BNOT_I", /* A B R(A) := ~R(B) */
"EQ_II", /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
"EQ_FF", /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
"LT_II", /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
"LT_FF", /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
"LE_II", /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
"LE_FF", /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
"TABLE_GETFIELD", /* A B C R(A) := R(B)[RK(C)], string key */
"TABLE_SETFIELD", /* A B C R(A)[RK(B)] := RK(C), string key */
"TABLE_SELF_SK", /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
"GETI", /* A B C R(A) := R(B)[RK(C)], integer key */
"SETI", /* A B C R(A)[RK(B)] := RK(C), integer key */
"GETFIELD", /* A B C R(A) := R(B)[RK(C)], string key */
"SELF_SK", /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
"SETFIELD", /* A B C R(A)[RK(B)] := RK(C), string key */
"GETTABUP_SK",
NULL};

@ -1,108 +0,0 @@
/*
** LuaJIT VM builder.
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
*/
#ifndef _BUILDVM_H
#define _BUILDVM_H
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "ravi_def.h"
#include "ravi_arch.h"
/* Hardcoded limits. Increase as needed. */
#define BUILD_MAX_RELOC 200 /* Max. number of relocations. */
/* Prefixes for generated labels. */
#define LABEL_PREFIX "ravi_"
#define LABEL_PREFIX_BC LABEL_PREFIX "BC_"
#define LABEL_PREFIX_FF LABEL_PREFIX "ff_"
#define LABEL_PREFIX_CF LABEL_PREFIX "cf_"
#define LABEL_PREFIX_FFH LABEL_PREFIX "ffh_"
#define LABEL_PREFIX_LIBCF LABEL_PREFIX "lib_cf_"
#define LABEL_PREFIX_LIBINIT LABEL_PREFIX "lib_init_"
/* Forward declaration. */
struct dasm_State;
/* Build modes. */
#define BUILDDEF(_) \
_(elfasm) _(coffasm) _(machasm) _(peobj) _(raw) \
_(bcdef)
typedef enum {
#define BUILDENUM(name) BUILD_##name,
BUILDDEF(BUILDENUM)
#undef BUILDENUM
BUILD__MAX
} BuildMode;
/* Code relocation. */
typedef struct BuildReloc {
/* Offset of the relocatable symbol computed as (symbol - code) */
int32_t RelativeOffset;
/* index into ExportedSymbolNames array? */
int sym;
/* type = 0 means absolute address, type = 1 means relative address */
int type;
} BuildReloc;
typedef struct BuildSym {
const char *name;
int32_t ofs;
} BuildSym;
/* Build context structure. */
typedef struct BuildCtx {
/* DynASM state pointer. Should be first member. */
struct dasm_State *D;
/* Parsed command line. */
BuildMode mode;
FILE *fp;
const char *outname;
char **args;
/* Code and symbols generated by DynASM. */
uint8_t *code;
size_t CodeSize;
/* Number of entries in dispatch table */
int SizeofDispatchTable;
/* Number of exported functions such as luaV_interp()*/
int NumberOfExportedSymbols;
/* Count of all symbols including exported symbols and dispatch table functions - should be NUM_OPCODES+1 VM function */
int NumberOfSymbols;
int nrelocsym;
/* Array of exported symbols excluding the start symbol */
void **ExportedSymbols;
/* Array of all symbols including exported symbols, start symbol and dispatch table entries */
BuildSym *AllSymbols;
/* Names of relocatable symbols - e.g. ImportedSymbols. Not sure why we need this and ImportedSymbolNames */
const char **RelocatableSymbolNames;
/* Offsets of lables in the dispatch table, one of each byte code */
int32_t *DispatchTableOffsets;
/* This is the first symbol (ravi_vm_asm_begin) - other symbols are relative to this one in the dispatch table */
const char *StartSymbol;
/* Strings generated by DynASM. */
/* ExportedSymbolNames will point to an array of symbol names corresponding to ExportedSymbols */
const char *const *ExportedSymbolNames;
/* ImportedSymbolNames is an array of names of external functions called from the VM - e.g. luaF_close */
const char *const *ImportedSymbolNames;
const char *dasm_ident;
const char *dasm_arch;
/* Relocatable symbols (addresses) */
BuildReloc Reloc[BUILD_MAX_RELOC];
/* Size of above (i.e. used elements) */
int RelocSize;
} BuildCtx;
extern void owrite(BuildCtx *ctx, const void *ptr, size_t sz);
extern void emit_asm(BuildCtx *ctx);
extern void emit_peobj(BuildCtx *ctx);
extern const char *const bc_names[];
#endif

@ -1,194 +0,0 @@
/*
** LuaJIT VM builder: Assembler source code emitter.
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
*/
#include "buildvm.h"
#include "lopcodes.h"
/* ------------------------------------------------------------------------ */
#if RAVI_TARGET_X86ORX64
/* Emit bytes piecewise as assembler text. */
static void emit_asm_bytes(BuildCtx *ctx, uint8_t *p, int n)
{
int i;
for (i = 0; i < n; i++) {
if ((i & 15) == 0)
fprintf(ctx->fp, "\t.byte %d", p[i]);
else
fprintf(ctx->fp, ",%d", p[i]);
if ((i & 15) == 15) putc('\n', ctx->fp);
}
if ((n & 15) != 0) putc('\n', ctx->fp);
}
/* Emit relocation */
static void emit_asm_reloc(BuildCtx *ctx, int type, const char *sym)
{
switch (ctx->mode) {
case BUILD_elfasm:
if (type)
fprintf(ctx->fp, "\t.long %s-.-4\n", sym);
else
fprintf(ctx->fp, "\t.long %s\n", sym);
break;
case BUILD_coffasm:
fprintf(ctx->fp, "\t.def %s; .scl 3; .type 32; .endef\n", sym);
if (type)
fprintf(ctx->fp, "\t.long %s-.-4\n", sym);
else
fprintf(ctx->fp, "\t.long %s\n", sym);
break;
default: /* BUILD_machasm for relative relocations handled below. */
fprintf(ctx->fp, "\t.long %s\n", sym);
break;
}
}
static const char *const jccnames[] = {
"jo", "jno", "jb", "jnb", "jz", "jnz", "jbe", "ja",
"js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg"
};
/* Emit x86/x64 text relocations. */
static void emit_asm_reloc_text(BuildCtx *ctx, uint8_t *cp, int n,
const char *sym)
{
const char *opname = NULL;
if (--n < 0) goto err;
if (cp[n] == 0xe8) {
opname = "call";
} else if (cp[n] == 0xe9) {
opname = "jmp";
} else if (cp[n] >= 0x80 && cp[n] <= 0x8f && n > 0 && cp[n-1] == 0x0f) {
opname = jccnames[cp[n]-0x80];
n--;
} else {
err:
fprintf(stderr, "Error: unsupported opcode for %s symbol relocation.\n",
sym);
exit(1);
}
emit_asm_bytes(ctx, cp, n);
if (strncmp(sym+(*sym == '_'), LABEL_PREFIX, sizeof(LABEL_PREFIX)-1)) {
/* Various fixups for external symbols outside of our binary. */
if (ctx->mode == BUILD_elfasm) {
if (RAVI_32)
fprintf(ctx->fp, "#if __PIC__\n\t%s lj_wrap_%s\n#else\n", opname, sym);
fprintf(ctx->fp, "\t%s %s@PLT\n", opname, sym);
if (RAVI_32)
fprintf(ctx->fp, "#endif\n");
return;
} else if (RAVI_32 && ctx->mode == BUILD_machasm) {
fprintf(ctx->fp, "\t%s L%s$stub\n", opname, sym);
return;
}
}
fprintf(ctx->fp, "\t%s %s\n", opname, sym);
}
#else
#error "missing relocation support for this architecture"
#endif
#define ELFASM_PX "@"
/* Emit an assembler label. */
static void emit_asm_label(BuildCtx *ctx, const char *name, int size, int isfunc)
{
switch (ctx->mode) {
case BUILD_elfasm:
fprintf(ctx->fp,
"\n\t.globl %s\n"
"\t.hidden %s\n"
"\t.type %s, " ELFASM_PX "%s\n"
"\t.size %s, %d\n"
"%s:\n",
name, name, name, isfunc ? "function" : "object", name, size, name);
break;
case BUILD_coffasm:
fprintf(ctx->fp, "\n\t.globl %s\n", name);
if (isfunc)
fprintf(ctx->fp, "\t.def %s; .scl 3; .type 32; .endef\n", name);
fprintf(ctx->fp, "%s:\n", name);
break;
case BUILD_machasm:
fprintf(ctx->fp,
"\n\t.private_extern %s\n"
"\t.no_dead_strip %s\n"
"%s:\n", name, name, name);
break;
default:
break;
}
}
/* Emit alignment. */
static void emit_asm_align(BuildCtx *ctx, int bits)
{
switch (ctx->mode) {
case BUILD_elfasm:
case BUILD_coffasm:
fprintf(ctx->fp, "\t.p2align %d\n", bits);
break;
case BUILD_machasm:
fprintf(ctx->fp, "\t.align %d\n", bits);
break;
default:
break;
}
}
/* ------------------------------------------------------------------------ */
/* Emit assembler source code. */
void emit_asm(BuildCtx *ctx)
{
int i, rel;
fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch);
fprintf(ctx->fp, "\t.text\n");
emit_asm_align(ctx, 4);
emit_asm_label(ctx, ctx->StartSymbol, 0, 0);
if (ctx->mode != BUILD_machasm)
fprintf(ctx->fp, ".Lbegin:\n");
for (i = rel = 0; i < ctx->NumberOfSymbols; i++) {
int32_t ofs = ctx->AllSymbols[i].ofs;
int32_t next = ctx->AllSymbols[i+1].ofs;
emit_asm_label(ctx, ctx->AllSymbols[i].name, next - ofs, 1);
while (rel < ctx->RelocSize && ctx->Reloc[rel].RelativeOffset <= next) {
BuildReloc *r = &ctx->Reloc[rel];
int n = r->RelativeOffset - ofs;
if (r->type != 0 &&
(ctx->mode == BUILD_elfasm || ctx->mode == BUILD_machasm)) {
emit_asm_reloc_text(ctx, ctx->code+ofs, n, ctx->RelocatableSymbolNames[r->sym]);
} else {
emit_asm_bytes(ctx, ctx->code+ofs, n);
emit_asm_reloc(ctx, r->type, ctx->RelocatableSymbolNames[r->sym]);
}
ofs += n+4;
rel++;
}
emit_asm_bytes(ctx, ctx->code+ofs, next-ofs);
}
fprintf(ctx->fp, "\n");
switch (ctx->mode) {
case BUILD_elfasm:
/* fallthrough */
case BUILD_coffasm:
fprintf(ctx->fp, "\t.ident \"%s\"\n", ctx->dasm_ident);
break;
case BUILD_machasm:
fprintf(ctx->fp,
"\t.cstring\n"
"\t.ascii \"%s\\0\"\n", ctx->dasm_ident);
break;
default:
break;
}
fprintf(ctx->fp, "\n");
}

@ -1,533 +0,0 @@
/*
** LuaJIT VM builder: PE object emitter.
** Modified for Ravi - no longer compatible with LuaJIT.
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
**
** Only used for building on Windows, since we cannot assume the presence
** of a suitable assembler. The host and target byte order must match.
*/
#include "buildvm.h"
#include "lopcodes.h"
#if RAVI_TARGET_X86ORX64
/* IMPORTANT: Note that the code here depends upon Little Endian layout - i.e.
it assumes the compiler is generating Little Endian code. */
/* Context for PE object emitter. */
static char *strtab;
static size_t strtabofs;
/* -- PE object definitions ----------------------------------------------- */
/* PE header. */
typedef struct PEheader {
uint16_t Machine; /* The number that identifies the type of target machine */
uint16_t NumberOfSections; /* The number of sections. This indicates the size
of the section table, which immediately follows
the headers. */
uint32_t TimeDateStamp; /* The low 32 bits of the number of seconds since
00:00 January 1, 1970 (a C run-time time_t value),
that indicates when the file was created. */
uint32_t PointerToSymbolTable; /* The file offset of the COFF symbol table, or
zero if no COFF symbol table is present.
This value should be zero for an image
because COFF debugging information is
deprecated. */
uint32_t NumberOfSymbols; /* The number of entries in the symbol table. This
data can be used to locate the string table,
which immediately follows the symbol table. This
value should be zero for an image because COFF
debugging information is deprecated. */
uint16_t
SizeOfOptionalHeader; /* The size of the optional header, which is
required for executable files but not for object
files. This value should be zero for an object
file. */
uint16_t
Characteristics; /* The flags that indicate the attributes of the file */
} PEheader;
/* PE section. */
typedef struct PESectionHeader {
char name[8]; /* An 8-byte, null-padded UTF-8 encoded string. If the string is
exactly 8 characters long, there is no terminating null. For
longer names, this field contains a slash (/) that is
followed by an ASCII representation of a decimal number that
is an offset into the string table. Executable images do not
use a string table and do not support section names longer
than 8 characters. Long names in object files are truncated
if they are emitted to an executable file. */
uint32_t VirtualSize; /* The total size of the section when loaded into
memory. If this value is greater than SizeOfRawData,
the section is zero-padded. This field is valid only
for executable images and should be set to zero for
object files. */
uint32_t VirtualAddress; /* For executable images, the address of the first
byte of the section relative to the image base
when the section is loaded into memory. For object
files, this field is the address of the first byte
before relocation is applied; for simplicity,
compilers should set this to zero. Otherwise, it
is an arbitrary value that is subtracted from
offsets during relocation. */
uint32_t SizeOfRawData; /* The size of the section (for object files) or the
size of the initialized data on disk (for image
files). For executable images, this must be a
multiple of FileAlignment from the optional header.
If this is less than VirtualSize, the remainder of
the section is zero-filled. Because the
SizeOfRawData field is rounded but the VirtualSize
field is not, it is possible for SizeOfRawData to
be greater than VirtualSize as well. When a section
contains only uninitialized data, this field should
be zero. */
uint32_t PointerToRawData; /* The file pointer to the first page of the
section within the COFF file. For executable
images, this must be a multiple of FileAlignment
from the optional header. For object files, the
value should be aligned on a 4-byte boundary for
best performance. When a section contains only
uninitialized data, this field should be zero.
*/
uint32_t PointerToRelocations; /* The file pointer to the beginning of
relocation entries for the section. This is
set to zero for executable images or if
there are no relocations. */
uint32_t
PointerToLinenumbers; /* The file pointer to the beginning of line-number
entries for the section. This is set to zero if
there are no COFF line numbers. This value should
be zero for an image because COFF debugging
information is deprecated. */
uint16_t NumberOfRelocations; /* The number of relocation entries for the
section. This is set to zero for executable
images. */
uint16_t NumberOfLinenumbers; /* The number of line-number entries for the
section. This value should be zero for an
image because COFF debugging information is
deprecated. */
uint32_t Characteristics;
} PESectionHeader;
/* PE relocation. */
typedef struct PEreloc {
uint32_t VirtualAddress; /* The address of the item to which relocation is
applied. This is the offset from the beginning of the section, plus the value
of the section's RVA/Offset field. See Section Table (Section Headers). For
example, if the first byte of the section has an address of 0x10, the third
byte has an address of 0x12.*/
uint32_t SymbolTableIndex; /* A zero-based index into the symbol table. This
symbol gives the address that is to be used for the relocation. If the
specified symbol has section storage class, then the symbol's address is the
address with the first section of the same name.*/
uint16_t type;
} PEreloc;
/* Cannot use sizeof, because it pads up to the max. alignment. */
#define PEOBJ_RELOC_SIZE (sizeof(uint32_t) * 2 + sizeof(uint16_t))
/* PE symbol table entry. */
typedef struct PEsym {
union {
char ShortName[8]; /* An array of 8 bytes. This array is padded with nulls
on the right if the name is less than 8 bytes long. */
uint32_t nameref[2];
} n;
uint32_t Value; /* The value that is associated with the symbol. The
interpretation of this field depends on SectionNumber and
StorageClass. A typical meaning is the relocatable address.
*/
int16_t SectionNumber; /* The signed integer that identifies the section,
using a one-based index into the section table. Some
values have special meaning */
uint16_t Type; /* A number that represents type. Microsoft tools set this
field to 0x20 (function) or 0x0 (not a function). For more
information */
uint8_t StorageClass; /* An enumerated value that represents storage class. */
uint8_t NumberOfAuxSymbols; /* The number of auxiliary symbol table entries
that follow this record. */
} PEsym;
/* sizeof(PEsym) must be 18 */
#define PEOBJ_SYM_SIZE 18 // must be 18 bytes
/*
Zero or more auxiliary symbol-table records immediately follow each standard
symbol-table record. However, typically not more than one auxiliary symbol-table
record follows a standard symbol-table record (except for .file records with
long file names). Each auxiliary record is the same size as a standard
symbol-table record (18 bytes), but rather than define a new symbol, the
auxiliary record gives additional information on the last symbol defined. The
choice of which of several formats to use depends on the StorageClass field.
*/
/* PE symbol table auxiliary entry for a section. */
typedef struct PEsymaux {
uint32_t size;
uint16_t nreloc;
uint16_t nline;
uint32_t cksum;
uint16_t assoc;
uint8_t comdatsel;
uint8_t unused[3];
} PEsymaux;
/* PE object CPU specific defines. */
#define PEOBJ_ARCH_TARGET 0x8664 /* Image file AMD64 */
#define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */
#define PEOBJ_RELOC_DIR32 0x02
#define PEOBJ_RELOC_ADDR32NB 0x03
#define PEOBJ_RELOC_OFS 0
/* Section numbers (0-based). */
enum {
PEOBJ_SECT_ABS = -2,
PEOBJ_SECT_UNDEF = -1,
PEOBJ_SECT_TEXT,
PEOBJ_SECT_PDATA,
PEOBJ_SECT_XDATA,
PEOBJ_SECT_RDATA_Z,
PEOBJ_NSECTIONS
};
/* Symbol types. */
#define IMAGE_SYM_TYPE_NULL 0
#define IMAGE_SYM_TYPE_FUNC 0x20
/* Symbol storage class. */
#define IMAGE_SYM_CLASS_EXTERNAL 2
#define PEOBJ_SCL_STATIC 3
/* -- PE object emitter --------------------------------------------------- */
/* Emit PE object symbol. */
static void emit_peobj_sym(BuildCtx *ctx, const char *name, uint32_t value,
int sect, int type, int scl)
{
PEsym sym;
size_t len = strlen(name);
if (!strtab) { /* Pass 1: only calculate string table length. */
if (len > 8) strtabofs += len+1;
return;
}
if (len <= 8) {
memcpy(sym.n.ShortName, name, len);
memset(sym.n.ShortName+len, 0, 8-len);
} else {
sym.n.nameref[0] = 0;
sym.n.nameref[1] = (uint32_t)strtabofs;
memcpy(strtab + strtabofs, name, len);
strtab[strtabofs+len] = 0;
strtabofs += len+1;
}
sym.Value = value;
sym.SectionNumber = (int16_t)(sect+1); /* 1-based section number. */
sym.Type = (uint16_t)type;
sym.StorageClass = (uint8_t)scl;
sym.NumberOfAuxSymbols = 0;
owrite(ctx, &sym, PEOBJ_SYM_SIZE);
}
/* Emit PE object section symbol. */
static void emit_peobj_sym_sect(BuildCtx *ctx, PESectionHeader *sectionHeader, int sect)
{
PEsym sym;
PEsymaux aux;
if (!strtab) return; /* Pass 1: no output. */
memcpy(sym.n.ShortName, sectionHeader[sect].name, 8);
sym.Value = 0;
sym.SectionNumber = (int16_t)(sect+1); /* 1-based section number. */
sym.Type = IMAGE_SYM_TYPE_NULL;
sym.StorageClass = PEOBJ_SCL_STATIC;
sym.NumberOfAuxSymbols = 1;
owrite(ctx, &sym, PEOBJ_SYM_SIZE);
memset(&aux, 0, sizeof(PEsymaux));
aux.size = sectionHeader[sect].SizeOfRawData;
aux.nreloc = sectionHeader[sect].NumberOfRelocations;
owrite(ctx, &aux, PEOBJ_SYM_SIZE);
}
static inline int start_symbol_index(int NumberOfRelocatableSymbols) {
// Following is zero based offset of the symbol
// The symbol table is arranged thus (see emit_peobj()):
// @feat.00 - 1 symbol
// .text section header - 2 symbols
// NumberOfRelocatableSymbols Relocatable symbols
// .pdata section header - 2 symbols
// .xdata section header - 2 symbols
// Which gives following formula to get to ravi_vm_asm_begin (StartSymbol)
return 1 + 2 + NumberOfRelocatableSymbols + 2 + 2; // Points to StartSymbol
}
static inline int xdata_symbol_index(int NumberOfRelocatableSymbols) {
// Following is zero based offset of the symbol
// The symbol table is arranged thus (see emit_peobj()):
// @feat.00 - 1 symbol
// .text section header - 2 symbols
// NumberOfRelocatableSymbols Relocatable symbols
// .pdata section header - 2 symbols
// .xdata section header
return 1 + 2 + NumberOfRelocatableSymbols + 2; // Points to .xdata
}
/* Emit Windows PE object file. */
void emit_peobj(BuildCtx *ctx)
{
PEheader pehdr;
PESectionHeader sectionHeaders[PEOBJ_NSECTIONS];
uint32_t offset;
int i, NumberOfRelocatableSymbols;
union { uint8_t b; uint32_t u; } host_endian;
enum {
IMAGE_SCN_CNT_CODE = 0x00000020, /* The section contains executable code. */
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, /* The section contains initialized data. */
IMAGE_SCN_LNK_INFO = 0x00000200, /* The section contains comments or other information. The .drectve section has this Type. This is valid for object files only. */
IMAGE_SCN_ALIGN_4BYTES = 0x00300000, /* Align data on a 4-byte boundary. Valid only for object files. */
IMAGE_SCN_ALIGN_16BYTES = 0x00500000, /* Align data on a 16-byte boundary. Valid only for object files. */
IMAGE_SCN_MEM_READ = 0x40000000, /* The section can be read. */
IMAGE_SCN_MEM_EXECUTE = 0x20000000, /* The section can be executed as code. */
};
memset(&sectionHeaders, 0, sizeof sectionHeaders);
/* Set offset to end of the header and section headers */
offset = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PESectionHeader);
/* Fill in PE sections. */
/* The .text section will contain all the generated machine code. Note that this contains
exported symbols as well as the bytecode assembly routines; any external functions
referenced will count as requiring relocations */
memcpy(sectionHeaders[PEOBJ_SECT_TEXT].name, ".text", sizeof(".text")-1);
sectionHeaders[PEOBJ_SECT_TEXT].PointerToRawData = offset;
offset += (sectionHeaders[PEOBJ_SECT_TEXT].SizeOfRawData = (uint32_t)ctx->CodeSize);
sectionHeaders[PEOBJ_SECT_TEXT].PointerToRelocations = offset;
offset += (sectionHeaders[PEOBJ_SECT_TEXT].NumberOfRelocations = (uint16_t)ctx->RelocSize) * PEOBJ_RELOC_SIZE;
/* Flags: 60 = read+execute, 50 = align16, 20 = code. */
sectionHeaders[PEOBJ_SECT_TEXT].Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
/* The .pdata section contains a function table. Right now we only generate a single entry in the
function table, pointing to our exported luaV_interp() function which is the VM entrypoint and
meant to be a direct replacement of luaV_execute() */
memcpy(sectionHeaders[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1);
sectionHeaders[PEOBJ_SECT_PDATA].PointerToRawData = offset;
offset += (sectionHeaders[PEOBJ_SECT_PDATA].SizeOfRawData = 1*12); // We need one function table entry of 12 bytes (.pdata function table entry is made up of 3 * 4 byte fields)
sectionHeaders[PEOBJ_SECT_PDATA].PointerToRelocations = offset;
offset += (sectionHeaders[PEOBJ_SECT_PDATA].NumberOfRelocations = 3) * PEOBJ_RELOC_SIZE; // The 3 relocations are for the 3 fields in the .pdata function table entry above
/* Flags: 40 = read, 30 = align4, 40 = initialized data. */
sectionHeaders[PEOBJ_SECT_PDATA].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ;
/* The .xdata section contains the UNWIND_INFO structure for the exported function luaV_interp().
As the bytecode assembly routines are never invoked via 'call' I believe they are not treated as
C functions, hence inside the VM, the only function that needs to have unwind information defined
is the luaV_interp() function. (This is my current understanding) */
memcpy(sectionHeaders[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1);
sectionHeaders[PEOBJ_SECT_XDATA].PointerToRawData = offset;
offset += (sectionHeaders[PEOBJ_SECT_XDATA].SizeOfRawData = 24); /* This is the size of the UNWIND_INFO we write below for our generated code */
sectionHeaders[PEOBJ_SECT_XDATA].PointerToRelocations = offset;
offset += (sectionHeaders[PEOBJ_SECT_XDATA].NumberOfRelocations = 0) * PEOBJ_RELOC_SIZE; // No relocations
/* Flags: 40 = read, 30 = align4, 40 = initialized data. */
sectionHeaders[PEOBJ_SECT_XDATA].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ;
/* Don't think we really need this ... it just records dynasm version */
memcpy(sectionHeaders[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1);
sectionHeaders[PEOBJ_SECT_RDATA_Z].PointerToRawData = offset;
offset += (sectionHeaders[PEOBJ_SECT_RDATA_Z].SizeOfRawData = (uint32_t)strlen(ctx->dasm_ident)+1);
/* Flags: 40 = read, 30 = align4, 40 = initialized data. */
sectionHeaders[PEOBJ_SECT_RDATA_Z].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ;
/* Fill in PE header. */
pehdr.Machine = PEOBJ_ARCH_TARGET;
pehdr.NumberOfSections = PEOBJ_NSECTIONS;
pehdr.TimeDateStamp = 0; /* Timestamp is optional. */
pehdr.PointerToSymbolTable = offset;
pehdr.SizeOfOptionalHeader = 0;
pehdr.Characteristics = 0;
/* Compute the size of the symbol table:
** @feat.00 + nsections*2
** + asm_start + nsym
** + nrsym
*/
NumberOfRelocatableSymbols = ctx->nrelocsym;
pehdr.NumberOfSymbols = 1 + PEOBJ_NSECTIONS*2 + 1 + ctx->NumberOfSymbols + NumberOfRelocatableSymbols; // We count two symbols for each section header, 1 for @feat.00 and 1 for asm_start
/* Write PE object header and all sections. */
owrite(ctx, &pehdr, sizeof(PEheader));
owrite(ctx, &sectionHeaders, sizeof(PESectionHeader)*PEOBJ_NSECTIONS);
/* Write .text section. */
host_endian.u = 1;
if (host_endian.b != RAVI_ENDIAN_SELECT(1, 0)) {
fprintf(stderr, "Error: different byte order for host and target\n");
exit(1);
}
/* emit the machine code */
owrite(ctx, ctx->code, ctx->CodeSize);
/* emit all the symbols */
for (i = 0; i < ctx->RelocSize; i++) {
PEreloc reloc;
reloc.VirtualAddress = (uint32_t)ctx->Reloc[i].RelativeOffset + PEOBJ_RELOC_OFS;
reloc.SymbolTableIndex = 1+2+ctx->Reloc[i].sym; /* The symbolss are after @feat.00 (1) and .text sectionheader symbols (2) in the symbol table, hence we add 3 to the symbol's offset */
reloc.type = ctx->Reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32;
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
}
{ /* Write .pdata section. */
/*
The .pdata section contains an array of function table entries that are used for exception handling.
It is pointed to by the exception table entry in the image data directory. The entries must be sorted
according to the function addresses (the first field in each structure) before being emitted into the
final image. The target platform determines which of the three function table entry format variations
described below is used.
For x64 and Itanium platforms, function table entries have the following format:
Offset Size Field Description
0 4 Begin Address The RVA of the corresponding function
4 4 End Address The RVA of the end of the function.
8 4 Unwind Information The RVA of the unwind information.
*/
uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */
pdata[0] = 0;
pdata[1] = (uint32_t)ctx->CodeSize;
pdata[2] = 0; // Offset into .xdata I think (TBC)
owrite(ctx, &pdata, sizeof(pdata));
/*
Object files contain COFF relocations, which specify how the section data should be modified when placed in the image file and subsequently loaded into memory.
*/
PEreloc reloc;
/* Entry for pdata[0] */
reloc.VirtualAddress = 0;
reloc.SymbolTableIndex = start_symbol_index(NumberOfRelocatableSymbols); // Points to StartSymbol
reloc.type = PEOBJ_RELOC_ADDR32NB;
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
/* Entry for pdata[1] */
reloc.VirtualAddress = 4;
reloc.SymbolTableIndex = start_symbol_index(NumberOfRelocatableSymbols); // Points to StartSymbol
reloc.type = PEOBJ_RELOC_ADDR32NB;
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
/* Entry for pdata[2] */
reloc.VirtualAddress = 8;
reloc.SymbolTableIndex = xdata_symbol_index(NumberOfRelocatableSymbols); // Points to .xdata symbol
reloc.type = PEOBJ_RELOC_ADDR32NB;
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
}
{ /* Write .xdata section - this is the UNWIND_INFO data for luaV_interp() function */
// We want to record following UNWIND_CODEes (see structure in #if block below) in reverse order
// push rbp
// push rdi; push rsi; push rbx
// push r12; push r13; push r14; push r15; (see vm_x64.dasc)
#if 0
typedef enum _UNWIND_OP_CODES {
UWOP_PUSH_NONVOL = 0, /* info == register number */
UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */
UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
UWOP_SAVE_XMM128, /* info == XMM reg number, offset in next slot */
UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
} UNWIND_CODE_OPS;
typedef union _UNWIND_CODE {
struct {
uint8_t CodeOffset;
uint8_t UnwindOp : 4;
uint8_t OpInfo : 4;
};
uint16_t FrameOffset;
} UNWIND_CODE, *PUNWIND_CODE;
#define UNW_FLAG_EHANDLER 0x01
#define UNW_FLAG_UHANDLER 0x02
#define UNW_FLAG_CHAININFO 0x04
typedef struct _UNWIND_INFO {
uint8_t Version : 3;
uint8_t Flags : 5;
uint8_t SizeOfProlog;
uint8_t CountOfCodes;
uint8_t FrameRegister : 4;
uint8_t FrameOffset : 4;
UNWIND_CODE UnwindCode[1];
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
* union {
* OPTIONAL ULONG ExceptionHandler;
* OPTIONAL ULONG FunctionEntry;
* };
* OPTIONAL ULONG ExceptionData[]; */
} UNWIND_INFO, *PUNWIND_INFO;
#endif
/* Note that the registers and order below are dependent upon the order in which the
the registers were pushed in the prologue of luaV_interp() and are in the reverse order
here. This tells the OS that in case of exceptions, how to restore the registers when
unwinding the luaV_interp() function */
uint16_t xdata[12];
xdata[0] = 0x0001; /* Ver. 1, no handler, prolog size 0. */
xdata[1] = 0x0009; /* Number of unwind codes, no frame pointer. */
xdata[2] = 0x4200; /* Stack offset 4*8+8 = aword*5. */
xdata[3] = 0xF000; /* push r15 */
xdata[4] = 0xE000; /* push r14 */
xdata[5] = 0xD000; /* push r13 */
xdata[6] = 0xC000; /* push r12 */
xdata[7] = 0x3000; /* Push rbx. */
xdata[8] = 0x6000; /* Push rsi. */
xdata[9] = 0x7000; /* Push rdi. */
xdata[10] = 0x5000; /* Push rbp. */
xdata[11] = 0; /* Alignment - is this needed? TBC */
owrite(ctx, &xdata, sizeof(xdata));
}
/* Write .rdata$Z section. */
owrite(ctx, ctx->dasm_ident, strlen(ctx->dasm_ident)+1);
/* Write symbol table. */
/* This is done in two passes - the first pass collects string sizes, and second pass outputs the values */
/* Note that strtab being NULL triggers first pass behaviour (this is bad code but okay because we don't care here) */
strtab = NULL; /* 1st pass: collect string sizes. */
for (;;) {
strtabofs = 4;
/* Note the order in which the symbols are emitted - this order is important for the
various indices that are computed */
/* Mark as SafeSEH compliant. */
emit_peobj_sym(ctx, "@feat.00", 1,
PEOBJ_SECT_ABS, IMAGE_SYM_TYPE_NULL, PEOBJ_SCL_STATIC);
emit_peobj_sym_sect(ctx, sectionHeaders, PEOBJ_SECT_TEXT);
for (i = 0; i < NumberOfRelocatableSymbols; i++)
emit_peobj_sym(ctx, ctx->RelocatableSymbolNames[i], 0,
PEOBJ_SECT_UNDEF, IMAGE_SYM_TYPE_FUNC, IMAGE_SYM_CLASS_EXTERNAL);
emit_peobj_sym_sect(ctx, sectionHeaders, PEOBJ_SECT_PDATA);
emit_peobj_sym_sect(ctx, sectionHeaders, PEOBJ_SECT_XDATA);
emit_peobj_sym(ctx, ctx->StartSymbol, 0,
PEOBJ_SECT_TEXT, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_EXTERNAL);
for (i = 0; i < ctx->NumberOfSymbols; i++)
emit_peobj_sym(ctx, ctx->AllSymbols[i].name, (uint32_t)ctx->AllSymbols[i].ofs,
PEOBJ_SECT_TEXT, IMAGE_SYM_TYPE_FUNC, IMAGE_SYM_CLASS_EXTERNAL);
emit_peobj_sym_sect(ctx, sectionHeaders, PEOBJ_SECT_RDATA_Z);
if (strtab)
break;
/* 2nd pass: alloc strtab, write syms and copy strings. */
strtab = (char *)malloc(strtabofs);
*(uint32_t *)strtab = (uint32_t)strtabofs;
}
/* Write string table. */
owrite(ctx, strtab, strtabofs);
}
#else
void emit_peobj(BuildCtx *ctx)
{
UNUSED(ctx);
fprintf(stderr, "Error: no PE object support for this target\n");
exit(1);
}
#endif

File diff suppressed because it is too large Load Diff

@ -1,611 +0,0 @@
/*
Introduction
============
This is the code generator for the Lua/Ravi VM. It uses dynasm as the assembler.
The overall approach is:
The overall approach is:
* For each bytecode create an assembler routine
* Create a dispatch table with pointers to the assembler routines; the dispatch table is stored in the Lua global_State structure
but this could change in future
* Each assembler routine will (after completing its action) fetch the next bytecode instruction and jump to the next
assembler routine using the dispatch table
* The assembler routines are not full fledged C functions - they are part of one whole program. Hence they make assumptions about
register usage which will be documented below. The VM as a whole will have a fixed set of register allocations so that most
important information is held in registers.
Implementation Considerations
-----------------------------
* The dispatch table is stored in global_State - it is not clear yet whether it is worth making a local stack copy of it when the
VM starts executing.
Register Allocations
--------------------
The VM will use a fixed set of registers mostly with some register usage varying across routines. The following table shows the
planned usage.
Nomenclature
* cs - callee saved, if we call a C function then after it returns we can rely on these registers
* v - volatile, these registers may be overridden by a called function so do not rely on them after function call
* `(n)` - used to pass arg n to function
+--------------------+------------------+------------------------------+------------------------------------------+
+ Windows X64 reg | Linux X64 reg | Assignment | Notes |
+====================+==================+==============================+==========================================+
+ rbx (cs) | rbx (cs) | PC | Pointer to next bytecode |
+--------------------+------------------+------------------------------+------------------------------------------+
+ rbp (cs) | rbp (cs) | L | Pointer to lua_State |
+--------------------+------------------+------------------------------+------------------------------------------+
+ rdi (cs) | rdi (v) (1) | | |
+--------------------+------------------+------------------------------+------------------------------------------+
+ rsi (cs) | rsi (v) (2) | | |
+--------------------+------------------+------------------------------+------------------------------------------+
+ rsp (cs) | rsp | | Stack pointer |
+--------------------+------------------+------------------------------+------------------------------------------+
+ r12 (cs) | r12 (cs) | CI | CallInfo (Lua frame) |
+--------------------+------------------+------------------------------+------------------------------------------+
+ r13 (cs) | r13 (cs) | LCL | Current function's LClosure |
+--------------------+------------------+------------------------------+------------------------------------------+
+ r14 (cs) | r14 (cs) | DISPATCH | Ptr to Dispatch table |
+--------------------+------------------+------------------------------+------------------------------------------+
+ r15 (cs) | r15 (cs) | KBASE | Ptr to constants table in Proto |
+--------------------+------------------+------------------------------+------------------------------------------+
+ rax (v) | rax (v) | RCa | Scratch - upon entry to subroutine eax |
+ | | | will have the B,C portion of bytecode |
+--------------------+------------------+------------------------------+------------------------------------------+
+ rcx (v) (1) | rcx (v) (4) | RAa | Scratch - upon entry to subroutine ecx |
+ | | | will have the value of A in bytecode |
+--------------------+------------------+------------------------------+------------------------------------------+
+ rdx (v) (2) | rdx (v) (3) | RBa | Scratch - upon entry to subroutine edx |
+ | | | will have the OpCode |
+--------------------+------------------+------------------------------+------------------------------------------+
+ r8 (v) (3) | r8 (v) (5) | BASE | Pointer to Lua stack base |
+--------------------+------------------+------------------------------+------------------------------------------+
+ r9 (v) (4) | r9 (v) (6) | TMP3 | Scratch |
+--------------------+------------------+------------------------------+------------------------------------------+
+ r10 (v) | r10 (v) | TMP1 | Scratch |
+--------------------+------------------+------------------------------+------------------------------------------+
+ r11 (v) | r11 (v) | TMP2 | Scratch |
+--------------------+------------------+------------------------------+------------------------------------------+
Stack space
-----------
On Win64 every function gets a 32-byte shadow space for the 4 register arguments, which we can use. But we also need
to provide a shadow space for function calls inside the VM. Basically these 4 stack positions cancel out if we make use
of the slots provided by the caller.
*/
|.arch x64
|.section code_op, code_sub
|
|.actionlist build_actionlist
|.globals GLOB_
|.globalnames globnames
|.externnames extnames
|
|.define X64, 1
|.if WIN
|.define X64WIN, 1
|.endif
|
|// Fixed register assignments for the interpreter.
|//
|// BASE caches the Lua function's base pointer (start of Lua registers)
|// This is volatile, i.e. must be refetched after any call that can
|// reallocate the Lua stack (typically any Lua api call)
|//
|// KBASE caches the Lua function proto's constant table, this does not
|// change during the execution
|//
|// PC caches the program counter (current bytecode location)
|// We need to ensure that the PC is saved to CI->u.l.savedpc before calling certain functions
|//
|// DISPATCH points to the dispatch table which is located in the
|// global_State structure defined in lstate.h - this contains the computed goto
|// destinations
|//
|.define BASE, r8 // Not C callee-save, refetched anyway.
|.define KBASE, r15 // C callee-save.
|.define PC, rbx // C callee-save.
|.define DISPATCH, r14 // C callee-save.
|
|// TODO following is based on what LuaJIT does but could change
|.define RA, ecx
|.define RAH, ch
|.define RAL, cl
|.define RAa, rcx
|.define RB, edx
|.define RBW, dx
|.define RBH, dh
|.define RBL, dl
|.define RBa, rdx
|.define OP, RB
|.define RC, eax // volatile
|.define RCH, ah
|.define RCL, al
|.define RCW, ax
|.define RCa, rax
|
|.define TMP1, r10
|.define TMP1d, r10d
|.define TMP2, r11
|.define TMP3, r9
|.define TMP3d, r9d
|
|.if X64WIN
|
| // On Win64, the first four integer arguments are passed in registers. Integer values are passed
| // (in order left to right) in RCX, RDX, R8, and R9. Arguments five and higher are passed
| // on the stack. All arguments are right-justified in registers. This is done so the callee
| // can ignore the upper bits of the register if need be and can access only the portion
| // of the register necessary.
| // Floating-point and double-precision arguments are passed in XMM0 - XMM3 (up to 4)
| // with the integer slot (RCX, RDX, R8, and R9) that would normally be used for that cardinal
| // slot being ignored (see example below) and vice versa.
| // func3(int a, double b, int c, float d);
| // a in RCX, b in XMM1, c in R8, d in XMM3
| // For functions not fully prototyped, the caller will pass integer values as integers
| // and floating-point values as double precision. For floating-point values only, both
| // the integer register and the floating-point register will contain the float value
| // in case the callee expects the value in the integer registers.
|
|.define CARG1, rcx // x64/WIN64 C call arguments.
|.define CARG2, rdx
|.define CARG3, r8
|.define CARG4, r9
|.define CARG1d, ecx
|.define CARG2d, edx
|.define CARG3d, r8d
|.define CARG4d, r9d
|.else
|.define CARG1, rdi // x64/POSIX C call arguments.
|.define CARG2, rsi
|.define CARG3, rdx
|.define CARG4, rcx
|.define CARG5, r8
|.define CARG6, r9
|.define CARG1d, edi
|.define CARG2d, esi
|.define CARG3d, edx
|.define CARG4d, ecx
|.define CARG5d, r8d
|.define CARG6d, r9d
|.endif
|
|// Type definitions.
|// We associate a default register with some of the types
|.type L, lua_State, rbp
|.type GL, global_State
|.type TOP, TValue // L->top (calls/open ops).
|.type CI, CallInfo, r12 // L->ci (calls, locally).
|.type LCL, LClosure, r13 // func->value (calls).
|
|// Type definitions with local validity.
|.type LUASTATE, lua_State
|.type TVALUE, TValue
|.type VALUE, Value
|.type CINFO, CallInfo
|.type GCOBJECT, GCObject
|.type TSTRING, TString
|.type TABLE, Table
|.type CCLOSURE, CClosure
|.type LCLOSURE, LClosure
|.type PROTO, Proto
|.type UPVAL, UpVal
|.type NODE, Node
|
|// Stack layout while in interpreter.
|//-----------------------------------------------------------------------
|.if X64WIN // x64/Windows stack layout
|
|// CFRAME_SPACE defines how much space we allocate on the stack.
|// Note that on windows this includes the shadow space of 32 bytes we need
|// to provide when calling functions; but since we were also given 32 bytes
|// it all cancels out and we can keep stack allocation size the same
|// across Windows and Linux.
|
|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--).
|.macro saveregs
| // The registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 are considered nonvolatile
| // and must be saved and restored by a function that uses them.
| // There is always space to hold all parameters in the parameter area of the stack
| // so that each register parameter has a home address. Even if a function has less
| // than 4 parameters, at least 4 stack locatons is guaranteed and is owned by the
| // called function even if it doesn't use it
| // All memory beyond the current address of RSP is considered volatile.
| // A frame function is a function that allocates stack space, calls other functions,
| // saves nonvolatile registers, or uses exception handling. It also requires a
| // function table entry. A frame function requires a prolog and an epilog.
| // home location for RCX is [RSP + 8]
| // home location for RDX is [RSP + 16]
| // home location for R8 is [RSP + 24]
| // home location for R9 is [RSP + 32]
| push rbp; push rdi; push rsi; push rbx
| push r12; push r13; push r14; push r15;
| sub rsp, CFRAME_SPACE
|.endmacro
|.macro restoreregs
| add rsp, CFRAME_SPACE
| pop r15; pop r14; pop r13; pop r12;
| pop rbx; pop rsi; pop rdi; pop rbp
|.endmacro
|
|// IMPORTANT: On Win64 the prologue above must be recorded in an UNWIND_INFO
|// structure in the object file - this is done in buildvm_peobj.c. Therefore any change
|// to the prologue or stack allocation needs to be kept consistent between above and
|// the UNWIND_INFO structure.
|
|//-----------------------------------------------------------------------
|.else // x64/POSIX stack layout
|
|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--).
|.macro saveregs
| push rbp; push rbx; push r15; push r14
| push r13; push r12
| sub rsp, CFRAME_SPACE
|.endmacro
|.macro restoreregs
| add rsp, CFRAME_SPACE
| pop r12; pop r13
| pop r14; pop r15; pop rbx; pop rbp
|.endmacro
|
|.endif
|
|// Stack layout - total size is 16-byte aligned
|// All locations are relative to rsp
|// MEM1 to MEM5 are 8 byte stack slots we can use (40 bytes)
|// SAVE_* represent the locations of saved registers by function prologue
|.if X64WIN
|.define MEM5, aword [rsp+aword*17] // Caller provided shadow space, we can use
|.define MEM4, aword [rsp+aword*16] // Caller provided shadow space, we can use
|.define MEM3, aword [rsp+aword*15] // Caller provided shadow space, we can use
|.define MEM2, aword [rsp+aword*14] // Caller provided shadow space, we can use
|.define SAVE_RET, aword [rsp+aword*13] // return address, <-- rsp when we entered ravi_luaV_interp(), before prologue
|.define SAVE_R8, aword [rsp+aword*12] // pushed register
|.define SAVE_R7, aword [rsp+aword*11] // Pushed regsiter
|.define SAVE_R6, aword [rsp+aword*10] // pushed register
|.define SAVE_R5, aword [rsp+aword*9] // Pushed regsiter
|.define SAVE_R4, aword [rsp+aword*8] // Pushed register (prologue)
|.define SAVE_R3, aword [rsp+aword*7] // pushed register
|.define SAVE_R2, aword [rsp+aword*6] // Pushed regsiter
|.define SAVE_R1, aword [rsp+aword*5] // Pushed register (prologue)
|.define MEM1, aword [rsp+aword*4] // First stack location we can use (8 bytes)
|// Following four stack locations are the 32-byte shadow space for function calls
|// These stack locations may be over-written by any C function we call
|.define SHADOW4, aword [rsp+aword*3] //Shadow register arg
|.define SHADOW3, aword [rsp+aword*2] //Shadow register arg
|.define SHADOW2, aword [rsp+aword*1] //Shadow register arg
|.define SHADOW1, aword [rsp] //Shadow register arg, not to be used by VM, <-- rsp after interpreter prologue
|.else
|.define SAVE_RET, aword [rsp+aword*13] // return address, <-- rsp when we entered ravi_luaV_interp(), before prologue
|.define SAVE_R8, aword [rsp+aword*12] // pushed register
|.define SAVE_R7, aword [rsp+aword*11] // Pushed regsiter
|.define SAVE_R6, aword [rsp+aword*10] // pushed register
|.define SAVE_R5, aword [rsp+aword*9] // Pushed regsiter
|.define SAVE_R4, aword [rsp+aword*8] // Pushed register (prologue)
|.define SAVE_R3, aword [rsp+aword*7] // pushed register
|.define SAVE_R2, aword [rsp+aword*6] // Pushed regsiter
|.define SAVE_R1, aword [rsp+aword*5] // Pushed register (prologue)
|.define MEM5, aword [rsp+aword*4] // Stack space we can use
|.define MEM4, aword [rsp+aword*3] // Stack space we can use
|.define MEM3, aword [rsp+aword*2] // Stack space we can use
|.define MEM2, aword [rsp+aword*1] // Stack space we can use
|.define MEM1, aword [rsp] // First stack location we can use (8 bytes), <-- rsp after interpreter prologue
|.endif
|
|.define OPSIZE, 4 // sizeof(Instruction)
|.define PTRSIZE, 8 // sizeof(void *)
|.define VALUESIZE, 16 // sizeof(TValue)
|
|//The bytecode layout here uses LuaJIT inspired format.
|//
|//+---+---+---+----+
|//+ B | C | A | Op |
|//+---+---+---+----+
|//+ Bx | A | Op |
|//+-------+---+----+
|//+ Ax | Op |
|//+-----------+----+
|//
|// Thus we can directly access Op and A using AL and AH registers
|// Then we shift the value >> 16 which allows direct access to B, and C using AH, AL
|// or Bx using AX
|
|// Instruction decode+dispatch
|.macro dispatchNext
| mov RC, [PC] // Fetch next instruction
| movzx OP, RCL // OP = OpCode
| add PC, OPSIZE // PC++
| jmp aword [DISPATCH+OP*8] // jump to assembly routine
|.endmacro
|
|// Following macros decode the bytecode values A, B, C, etc.
|// They assume that RC holds the bytecode
|// Note that below we expect the bytecode layout to be like LuaJIT's
|// and ot Lua's - see lopcodes.h for details.
|.macro ins_ABC
| movzx RA, RCH // RA = A
| shr RC, 16 // RC = RC >> 16, now contains B,C
| movzx RB, RCH
| movzx RC, RCL;
|.endmacro
|.macro ins_ABx
| movzx RA, RCH // RA = A
| shr RC, 16 // RC = RC >> 16, now contains Bx
| movzx RB, RCW
|.endmacro
|.macro ins_AB_
| movzx RA, RCH // RA = A
| shr RC, 16 // RC = RC >> 16, now contains B,-
| movzx RB, RCH
|.endmacro
|.macro ins_A_C
| movzx RA, RCH // RA = A
| shr RC, 16 // RC = RC >> 16, now contains -,C
| movzx RC, RCL
|.endmacro
|.macro ins_A__
| movzx RA, RCH // RA = A
|.endmacro
|.macro ins_Bx
| shr RC, 16 // RC = RC >> 16, now contains Bx
| movzx RB, RCW
|.endmacro
|
|// Load effective address of BASE[reg*16] into dest
|.macro loadRegPtr, dest, reg
| shl reg, 4 // Multiply by 16, 2^4 = 16
| lea dest, [BASE+reg]
|.endmacro
|// Load effective address of K[reg*16] into dest
|.macro loadKonstPtr, dest, reg
| shl reg, 4 // Multiply by 16, 2^4 = 16
| lea dest, [KBASE+reg]
|.endmacro
|// Copy value from src to dst, using tmpq (64-bit) and tmpd (32-bit) registers as temporaries
|.macro copyValue, dst, src, tmpq, tmpd
| mov tmpq, TVALUE:src->value_.gc
| mov tmpd, TVALUE:src->tt_
| mov TVALUE:dst->value_.gc, tmpq
| mov TVALUE:dst->tt_, tmpd
|.endmacro
|// Computes signed shift to the PC
|.macro branchPC, reg
| lea PC, [PC+reg*4-MAXARG_sBx*4] // 131072 = MAXARG_sBx*4
|.endmacro
|
/* Generate subroutines used by opcodes and other parts of the VM. */
/* The .code_sub section should be last to help static branch prediction. */
static void build_subroutines(BuildCtx *ctx)
{
|.code_sub
|
|//-----------------------------------------------------------------------
|//-- VM entry point
|//-----------------------------------------------------------------------
|->luaV_interp:
| saveregs // prologue, save regs and adjust stack pointer
| mov L, CARG1 // save L (arg1)
| mov DISPATCH, L->l_G // retrieve global_State
| add DISPATCH, DISPATCH_OFFSET // retrieve the dispatch table
| mov CI, L->ci // save L->ci
| or word CI->callstatus, CIST_FRESH // ci->callstatus |= CIST_FRESH
|->new_frame: // OP_RETURN jumps to here after returning from Lua function
| mov TVALUE:TMP1, CI->func // Get ci->func
| mov LCL, TVALUE:TMP1->value_.gc // LCL = (LClosure *)(ci->func->value_.gc)
| mov BASE, CI->u.l.base // BASE = ci->u.l.base (volatile)
| mov PC, LCL->p // KBASE = LCL->p->k
| mov KBASE, PROTO:PC->k //
| mov PC, CI->u.l.savedpc // PC = CI->u.l.savedpc, type is Instruction*
| dispatchNext // Fetch instruction, increment PC and go to fetched instruction's label
|
|//-----------------------------------------------------------------------
|//-- Return handling ----------------------------------------------------
|//-----------------------------------------------------------------------
|
|->vm_return:
| restoreregs
| ret
}
static void build_OP_RETURN(BuildCtx *ctx)
{
|// Our goal is to generate following
|//
|// vmcase(OP_RETURN) {
|// int b = GETARG_B(i);
|// if (cl->p->sizep > 0) luaF_close(L, base);
|// savepc(L);
|// int nres = (b != 0 ? b - 1 : cast_int(L->top - ra));
|// b = luaD_poscall(L, ci, ra, nres);
|// if (ci->callstatus & CIST_FRESH) {
|// return b;
|// }
|// else {
|// ci = L->ci;
|// if (b) L->top = ci->top;
|// goto newframe; /* restart luaV_execute over new Lua function */
|// }
|// }
|
|// Upon entry RC has bytecode and OP has opcode
|
| mov PROTO:TMP1, LCL->p // TMP1 = ci->p
| cmp dword PROTO:TMP1->sizep, 0 // Test ci->p->sizep == 0
| jz >1 // Skip call to luaF_close
|
| // Call luaF_close
| mov KBASE, RCa // Save the bytecode into KBASE as we don't need KBASE anymore
| mov LCL, BASE // Don't need LCL anymore so use it to save BASE
| mov CARG1, L // arg1 = L
| mov CARG2, BASE // arg2 = base
| call extern luaF_close // call luaF_close
| mov BASE, LCL // restore BASE
| mov RCa, KBASE // Restore bytecode to RC
|
|1:
| mov CI->u.l.savedpc, PC // CI->u.l.savedpc = PC i.e. savepc(L)
| ins_AB_ // Decode bytecode, RA = A, RB = B
| mov TMP1d, RA // save RA, as CARG4 conflicts with RA on Linux (we could do this conditionally)
| test RB, RB // To test if RB (b) is zero
| je >2 // If b == 0 then jump to 2
| dec RB // RB = b - 1
| mov CARG4d, RB // CARG4 will be zero extended as RB=b is 32-bit operand, b cannnot be < 0
| loadRegPtr CARG3, TMP1d // CARG3 = ptr to Lua reg A, CARG3 conflicts with RB on Linux, TMP1 = RA here
| jmp >3
|2:
| loadRegPtr CARG3, TMP1d // CARG3 = ptr to Lua reg A, CARG3 conflicts with RB on Linux, TMP1 = RA here
| mov CARG4, L->top // CARG4 = L->top
| sub CARG4, CARG3 // CARG4 = L->top - R(A)
| shr CARG4, 4 // Divide by 16 as sizeof(TValue) = 16, use macro here?
|3:
| mov CARG1, L // CARG1 = L
| mov CARG2, CI // CARG2 = CI
| call extern luaD_poscall
| test word CI->callstatus, CIST_FRESH // callstatus & CIT_FRESH?
| jne ->vm_return // CI->callstatus & CIST_FRESH so return RAX which has b
| mov CI, L->ci
| test eax, eax // Is b == 0?
| je >4 // Yes, so skip next step
| mov LCL, CI->top // Using LCL as a temp register here as we don't need LCL anymore
| mov L->top, LCL // b != 0 therefore L->top = ci->top
|4:
| jmp ->new_frame // Resume the function (L and CI set)
|
}
static void build_OP_LOADK(BuildCtx *ctx)
{
|// TValue *rb = k + GETARG_Bx(i);
|// setobj2s(L, ra, rb);
|
| ins_ABx // RA = A, RB = Bx
| loadKonstPtr TMP1, RB // TMP1 = ptr to K[RB]
| loadRegPtr TMP2, RA // TMP2 = ptr to BASE[RA]
| copyValue TMP2, TMP1, RCa, TMP3d // Copy value at TMP1 to TMP2, using RCa, TMP3d as temp registers
| dispatchNext
}
static void build_OP_MOVE(BuildCtx *ctx)
{
|// setobjs2s(L, ra, RB(i));
|
| ins_AB_ // RA = A, RB = B
| loadRegPtr TMP1, RB // TMP1 = ptr to BASE[RB]
| loadRegPtr TMP2, RA // TMP2 = ptr to BASE[RA]
| copyValue TMP2, TMP1, RCa, TMP3d // Copy value at TMP1 to TMP2, using RCa, TMP3d as temp registers
| dispatchNext
}
static void build_OP_FORPREP_IP(BuildCtx *ctx, OpCode op)
{
|// vmcase(OP_RAVI_FORPREP_IP)
|// vmcase(OP_RAVI_FORPREP_I1) {
|// TValue *pinit = ra;
|// TValue *pstep = RAVI_LIKELY((op == OP_RAVI_FORPREP_I1)) ? NULL : ra + 2;
|// lua_Integer initv = ivalue(pinit);
|// lua_Integer istep = RAVI_LIKELY((op == OP_RAVI_FORPREP_I1)) ? 1 : ivalue(pstep);
|// setivalue(pinit, initv - istep);
|// pc += GETARG_sBx(i);
|// vmbreak;
|// }
|
| ins_ABx // RA = A, RB = Bx
| loadRegPtr RCa, RA // RCa is now pinit, we don't need RA anymore
| mov TMP1, TVALUE:RCa->value_.i // Load ivalue(pinit), TMP1 is now initv
if (op == OP_RAVI_FORPREP_I1) {
| dec TMP1 // step is 1
}
else {
| sub TMP1, [RCa+32] // idx = idx - ivalue(pstep), we rely upon TValue having data first
}
| mov TVALUE:RCa->value_.i, TMP1 // setivalue(pinit, initv - istep)
| branchPC RBa // pc += sBx
| dispatchNext // jump to next instruction
}
static void build_OP_FORLOOP_IP(BuildCtx *ctx, OpCode op)
{
|// vmcase(OP_RAVI_FORLOOP_IP)
|// vmcase(OP_RAVI_FORLOOP_I1) {
|// lua_Integer step = op == OP_RAVI_FORLOOP_I1 ? 1 : ivalue(ra + 2);
|// lua_Integer idx = ivalue(ra) + step; /* increment index */
|// lua_Integer limit = ivalue(ra + 1);
|// if (idx <= limit) {
|// pc += GETARG_sBx(i); /* jump back */
|// chgivalue(ra, idx); /* update internal index... */
|// setivalue(ra + 3, idx); /* ...and external index */
|// }
|// vmbreak;
|// }
|
|// RC holds the instruction
| ins_A__ // RA = A, RCa still needed for later
| loadRegPtr TMP3, RA // TMP3 now points to RA (idx)
| mov TMP1, TVALUE:TMP3->value_.i // Load ivalue(pinit), TMP1 is now idx
if (op == OP_RAVI_FORLOOP_I1) {
| inc TMP1 // step is 1
}
else {
| add TMP1, [TMP3+32] // Add step which is at ra+2, 32 = 2*sizeof(TValue); we rely on TValue having data first
}
| cmp TMP1, [TMP3+16] // compare idx with limit (ra+1), 16 = 1*sizeof(TValue); we rely on TValue having data first
| jg >1 // Our index has crossed the limit so we are done looping
| mov TVALUE:TMP3->value_.i, TMP1 // update index for internal var
| lea TMP2, [TMP3+48] // TMP2 now points to ra+3, 48 = 3*sizeof(TValue)
| mov TVALUE:TMP2->value_.i, TMP1 // External idx
| mov word TVALUE:TMP2->tt_, LUA_TNUMINT // Set type of external idx
| ins_Bx // RB = Bx, RCa used here
| branchPC RBa // PC += sBx
|1:
| dispatchNext
}
/* Generate the code for a single instruction. */
static void build_ins(BuildCtx *ctx, OpCode op, int defop)
{
int vk = 0;
|=>defop:
switch (op) {
case OP_RETURN:
build_OP_RETURN(ctx);
break;
case OP_LOADK:
build_OP_LOADK(ctx);
break;
case OP_MOVE:
build_OP_MOVE(ctx);
break;
case OP_RAVI_FORLOOP_IP:
case OP_RAVI_FORLOOP_I1:
build_OP_FORLOOP_IP(ctx, op);
break;
case OP_RAVI_FORPREP_I1:
case OP_RAVI_FORPREP_IP:
build_OP_FORPREP_IP(ctx, op);
break;
/* ---------------------------------------------------------------------- */
default:
| dispatchNext
break;
}
}
static int build_backend(BuildCtx *ctx)
{
int op;
dasm_growpc(Dst, NUM_OPCODES);
build_subroutines(ctx);
|.code_op
for (op = 0; op < NUM_OPCODES; op++)
build_ins(ctx, (OpCode)op, op);
return NUM_OPCODES;
}
Loading…
Cancel
Save