|
dvander@367
|
1 |
/** |
|
danderson@3977
|
2 |
* vim: set ts=4 sw=4 tw=99 et: |
|
ds@1330
|
3 |
* ============================================================================= |
|
dvander@2114
|
4 |
* SourceMod |
|
dvander@2114
|
5 |
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. |
|
ds@1330
|
6 |
* ============================================================================= |
|
dvander@367
|
7 |
* |
|
dvander@2114
|
8 |
* This program is free software; you can redistribute it and/or modify it under |
|
dvander@2114
|
9 |
* the terms of the GNU General Public License, version 3.0, as published by the |
|
dvander@2114
|
10 |
* Free Software Foundation. |
|
dvander@2114
|
11 |
* |
|
dvander@2114
|
12 |
* This program is distributed in the hope that it will be useful, but WITHOUT |
|
dvander@2114
|
13 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
dvander@2114
|
14 |
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
|
dvander@2114
|
15 |
* details. |
|
dvander@2114
|
16 |
* |
|
dvander@2114
|
17 |
* You should have received a copy of the GNU General Public License along with |
|
dvander@2114
|
18 |
* this program. If not, see <http://www.gnu.org/licenses/>. |
|
dvander@2114
|
19 |
* |
|
dvander@2114
|
20 |
* As a special exception, AlliedModders LLC gives you permission to link the |
|
dvander@2114
|
21 |
* code of this program (as well as its derivative works) to "Half-Life 2," the |
|
dvander@2114
|
22 |
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software |
|
dvander@2114
|
23 |
* by the Valve Corporation. You must obey the GNU General Public License in |
|
dvander@2114
|
24 |
* all respects for all other code used. Additionally, AlliedModders LLC grants |
|
dvander@2114
|
25 |
* this exception to all derivative works. AlliedModders LLC defines further |
|
dvander@2114
|
26 |
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), |
|
dvander@2114
|
27 |
* or <http://www.sourcemod.net/license.php>. |
|
dvander@367
|
28 |
* |
|
dvander@367
|
29 |
* Version: $Id$ |
|
dvander@367
|
30 |
*/ |
|
dvander@367
|
31 |
|
|
dvander@157
|
32 |
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_H_ |
|
dvander@157
|
33 |
#define _INCLUDE_SOURCEPAWN_JIT_X86_H_ |
|
dvander@157
|
34 |
|
|
dvander@157
|
35 |
#include <sp_vm_types.h> |
|
dvander@157
|
36 |
#include <sp_vm_api.h> |
|
dvander@2226
|
37 |
#include <KeCodeAllocator.h> |
|
danderson@3979
|
38 |
#include <macro-assembler-x86.h> |
|
danderson@3977
|
39 |
#include <ke_vector.h> |
|
dvander@2226
|
40 |
#include "jit_shared.h" |
|
dvander@2226
|
41 |
#include "BaseRuntime.h" |
|
dvander@3990
|
42 |
#include "sp_vm_basecontext.h" |
|
dvander@2226
|
43 |
#include "jit_function.h" |
|
danderson@3977
|
44 |
#include "opcodes.h" |
|
dvander@157
|
45 |
|
|
dvander@157
|
46 |
using namespace SourcePawn; |
|
dvander@157
|
47 |
|
|
danderson@3977
|
48 |
#define JIT_INLINE_ERRORCHECKS (1<<0) |
|
danderson@3977
|
49 |
#define JIT_INLINE_NATIVES (1<<1) |
|
danderson@3977
|
50 |
#define STACK_MARGIN 64 //8 parameters of safety, I guess |
|
danderson@3977
|
51 |
#define JIT_FUNCMAGIC 0x214D4148 //magic function offset |
|
dvander@157
|
52 |
|
|
danderson@3977
|
53 |
#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble |
|
danderson@3977
|
54 |
#define JITVARS_BASECTX 1 //important: don't change this aWOAWOGJQG I LIKE HAM |
|
danderson@3977
|
55 |
#define JITVARS_PROFILER 2 //profiler |
|
danderson@3977
|
56 |
#define JITVARS_PLUGIN 3 //sp_plugin_t |
|
dvander@157
|
57 |
|
|
danderson@3977
|
58 |
#define sDIMEN_MAX 5 //this must mirror what the compiler has. |
|
dvander@1396
|
59 |
|
|
dvander@2193
|
60 |
#define GET_CONTEXT(c) ((IPluginContext *)c->vm[JITVARS_BASECTX]) |
|
dvander@2193
|
61 |
|
|
dvander@157
|
62 |
typedef struct tracker_s |
|
dvander@157
|
63 |
{ |
|
danderson@3977
|
64 |
size_t size; |
|
danderson@3977
|
65 |
ucell_t *pBase; |
|
danderson@3977
|
66 |
ucell_t *pCur; |
|
dvander@157
|
67 |
} tracker_t; |
|
dvander@157
|
68 |
|
|
dvander@175
|
69 |
typedef struct funcinfo_s |
|
dvander@175
|
70 |
{ |
|
danderson@3977
|
71 |
unsigned int magic; |
|
danderson@3977
|
72 |
unsigned int index; |
|
dvander@175
|
73 |
} funcinfo_t; |
|
dvander@175
|
74 |
|
|
dvander@175
|
75 |
typedef struct functracker_s |
|
dvander@175
|
76 |
{ |
|
danderson@3977
|
77 |
unsigned int num_functions; |
|
danderson@3977
|
78 |
unsigned int code_size; |
|
dvander@175
|
79 |
} functracker_t; |
|
dvander@175
|
80 |
|
|
danderson@3977
|
81 |
struct CallThunk |
|
faluco@831
|
82 |
{ |
|
danderson@3977
|
83 |
Label call; |
|
danderson@3977
|
84 |
cell_t pcode_offset; |
|
faluco@831
|
85 |
|
|
danderson@3977
|
86 |
CallThunk(cell_t pcode_offset) |
|
danderson@3977
|
87 |
: pcode_offset(pcode_offset) |
|
danderson@3977
|
88 |
{ |
|
danderson@3977
|
89 |
} |
|
dvander@2226
|
90 |
}; |
|
dvander@2226
|
91 |
|
|
dvander@157
|
92 |
class CompData : public ICompilation |
|
dvander@157
|
93 |
{ |
|
dvander@157
|
94 |
public: |
|
danderson@3977
|
95 |
CompData() |
|
danderson@3977
|
96 |
: profile(0), |
|
danderson@3977
|
97 |
inline_level(0) |
|
danderson@3977
|
98 |
{ |
|
danderson@3977
|
99 |
}; |
|
danderson@3977
|
100 |
bool SetOption(const char *key, const char *val); |
|
danderson@3977
|
101 |
void Abort(); |
|
dvander@157
|
102 |
public: |
|
danderson@3977
|
103 |
cell_t cur_func; /* current func pcode offset */ |
|
danderson@3977
|
104 |
/* Options */ |
|
danderson@3977
|
105 |
int profile; /* profiling flags */ |
|
danderson@3977
|
106 |
int inline_level; /* inline optimization level */ |
|
danderson@3977
|
107 |
/* Per-compilation properties */ |
|
danderson@3977
|
108 |
unsigned int func_idx; /* current function index */ |
|
danderson@3977
|
109 |
}; |
|
danderson@3977
|
110 |
|
|
danderson@3977
|
111 |
class Compiler |
|
danderson@3977
|
112 |
{ |
|
danderson@3977
|
113 |
public: |
|
danderson@3977
|
114 |
Compiler(BaseRuntime *rt, cell_t pcode_offs); |
|
danderson@3977
|
115 |
~Compiler(); |
|
danderson@3977
|
116 |
|
|
danderson@3977
|
117 |
JitFunction *emit(int *errp); |
|
danderson@3977
|
118 |
|
|
danderson@3977
|
119 |
private: |
|
danderson@3977
|
120 |
bool setup(cell_t pcode_offs); |
|
danderson@3977
|
121 |
bool emitOp(OPCODE op); |
|
danderson@3977
|
122 |
cell_t readCell(); |
|
danderson@3977
|
123 |
|
|
danderson@3977
|
124 |
private: |
|
danderson@3977
|
125 |
Label *labelAt(size_t offset); |
|
danderson@3977
|
126 |
bool emitCall(); |
|
danderson@3977
|
127 |
bool emitNativeCall(OPCODE op); |
|
danderson@3977
|
128 |
bool emitSwitch(); |
|
danderson@3977
|
129 |
void emitGenArray(bool autozero); |
|
danderson@3977
|
130 |
void emitCallThunks(); |
|
danderson@3977
|
131 |
void emitCheckAddress(Register reg); |
|
danderson@3977
|
132 |
void emitErrorPath(Label *dest, int code); |
|
danderson@3977
|
133 |
void emitErrorPaths(); |
|
danderson@3977
|
134 |
|
|
dvander@3990
|
135 |
ExternalAddress cipAddr() { |
|
dvander@3990
|
136 |
sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); |
|
dvander@3990
|
137 |
return ExternalAddress(&ctx->cip); |
|
dvander@3990
|
138 |
} |
|
dvander@3991
|
139 |
ExternalAddress hpAddr() { |
|
dvander@3991
|
140 |
sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); |
|
dvander@3991
|
141 |
return ExternalAddress(&ctx->hp); |
|
dvander@3991
|
142 |
} |
|
dvander@3992
|
143 |
ExternalAddress frmAddr() { |
|
dvander@3992
|
144 |
sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); |
|
dvander@3992
|
145 |
return ExternalAddress(&ctx->frm); |
|
dvander@3992
|
146 |
} |
|
dvander@3990
|
147 |
|
|
danderson@3977
|
148 |
private: |
|
danderson@3977
|
149 |
AssemblerX86 masm; |
|
danderson@3977
|
150 |
BaseRuntime *rt_; |
|
danderson@3977
|
151 |
const sp_plugin_t *plugin_; |
|
danderson@3977
|
152 |
int error_; |
|
danderson@3977
|
153 |
uint32_t pcode_start_; |
|
danderson@3977
|
154 |
cell_t *code_start_; |
|
danderson@3977
|
155 |
cell_t *cip_; |
|
danderson@3977
|
156 |
cell_t *code_end_; |
|
danderson@3977
|
157 |
Label *jump_map_; |
|
danderson@3977
|
158 |
|
|
danderson@3977
|
159 |
// Errors |
|
danderson@3977
|
160 |
Label error_bounds_; |
|
danderson@3977
|
161 |
Label error_heap_low_; |
|
danderson@3977
|
162 |
Label error_heap_min_; |
|
danderson@3977
|
163 |
Label error_stack_low_; |
|
danderson@3977
|
164 |
Label error_stack_min_; |
|
danderson@3977
|
165 |
Label error_divide_by_zero_; |
|
danderson@3977
|
166 |
Label error_memaccess_; |
|
danderson@3977
|
167 |
Label error_integer_overflow_; |
|
danderson@3977
|
168 |
Label extern_error_; |
|
danderson@3977
|
169 |
|
|
danderson@3977
|
170 |
ke::Vector<CallThunk *> thunks_; //:TODO: free |
|
dvander@157
|
171 |
}; |
|
dvander@157
|
172 |
|
|
dvander@2193
|
173 |
class JITX86 |
|
dvander@157
|
174 |
{ |
|
danderson@3977
|
175 |
public: |
|
danderson@3977
|
176 |
JITX86(); |
|
danderson@3977
|
177 |
|
|
danderson@3977
|
178 |
public: |
|
danderson@3977
|
179 |
bool InitializeJIT(); |
|
danderson@3977
|
180 |
void ShutdownJIT(); |
|
danderson@3977
|
181 |
ICompilation *StartCompilation(BaseRuntime *runtime); |
|
danderson@3977
|
182 |
ICompilation *StartCompilation(); |
|
danderson@3977
|
183 |
void SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx); |
|
danderson@3977
|
184 |
void FreeContextVars(sp_context_t *ctx); |
|
danderson@3977
|
185 |
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData); |
|
danderson@3977
|
186 |
void DestroyFakeNative(SPVM_NATIVE_FUNC func); |
|
danderson@3977
|
187 |
JitFunction *CompileFunction(BaseRuntime *runtime, cell_t pcode_offs, int *err); |
|
danderson@3977
|
188 |
ICompilation *ApplyOptions(ICompilation *_IN, ICompilation *_OUT); |
|
danderson@3977
|
189 |
int InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result); |
|
danderson@3977
|
190 |
|
|
danderson@3977
|
191 |
public: |
|
danderson@3977
|
192 |
ExternalAddress GetUniversalReturn() { |
|
danderson@3977
|
193 |
return ExternalAddress(m_pJitReturn); |
|
danderson@3977
|
194 |
} |
|
danderson@3977
|
195 |
void *AllocCode(size_t size); |
|
danderson@3977
|
196 |
void FreeCode(void *code); |
|
danderson@3977
|
197 |
|
|
danderson@3977
|
198 |
private: |
|
danderson@3977
|
199 |
void *m_pJitEntry; /* Entry function */ |
|
danderson@3977
|
200 |
void *m_pJitReturn; /* Universal return address */ |
|
dvander@157
|
201 |
}; |
|
dvander@157
|
202 |
|
|
danderson@3977
|
203 |
const Register pri = eax; |
|
danderson@3977
|
204 |
const Register alt = edx; |
|
danderson@3977
|
205 |
const Register stk = edi; |
|
danderson@3977
|
206 |
const Register dat = ebp; |
|
danderson@3977
|
207 |
const Register tmp = ecx; |
|
danderson@3977
|
208 |
const Register info = esi; |
|
danderson@3977
|
209 |
const Register frm = ebx; |
|
danderson@3977
|
210 |
|
|
dvander@3982
|
211 |
struct InfoVars { |
|
dvander@3982
|
212 |
void *esp; |
|
dvander@3982
|
213 |
}; |
|
dvander@3982
|
214 |
|
|
dvander@3984
|
215 |
#define AMX_INFO_NSTACK offsetof(InfoVars, esp) |
|
dvander@157
|
216 |
|
|
dvander@2226
|
217 |
extern Knight::KeCodeCache *g_pCodeCache; |
|
dvander@2226
|
218 |
extern JITX86 g_Jit; |
|
dvander@157
|
219 |
|
|
dvander@157
|
220 |
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_ |