issue #179 removed ASMVM but it is available on asmvm branch
parent
72067c0893
commit
7834343893
@ -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 ..
|
@ -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
|
@ -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(§ionHeaders, 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, §ionHeaders, 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…
Reference in new issue