7875fe1acd
1) JIT compilation/optimization now occurs per-function, and only when functions are first used. We're now officially a whole-method JIT rather than an AOT compiler (albiet, still a simple JIT). This has two implications: Functions are now much better abstracted internally, and loading a plugin is now much less expensive. If a function contains calls to other functions, THOSE functions are only compiled when they're invoked as well. 2) I've removed debug mode. We always show full backtraces now, as there was a very cheap way to implement this which really cleaned up everything. This is great for a number of reasons -- there's less code, the JIT is better designed, we don't need to relocate debug tables, and best of all we no longer have to tell users to enable debug mode at their own expense. --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402459
318 lines
9.6 KiB
C
318 lines
9.6 KiB
C
/**
|
|
* vim: set ts=4 :
|
|
* =============================================================================
|
|
* SourceMod
|
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
* =============================================================================
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
* Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
* this exception to all derivative works. AlliedModders LLC defines further
|
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
* or <http://www.sourcemod.net/license.php>.
|
|
*
|
|
* Version: $Id$
|
|
*/
|
|
|
|
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
|
|
#define _INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
|
|
|
|
#include "../jit_helpers.h"
|
|
|
|
/**
|
|
* This outputs the execution function for a plugin.
|
|
* It also returns the 'return' offset, which is used for
|
|
* breaking out of the JIT during runtime.
|
|
*/
|
|
jitoffs_t Write_Execute_Function(JitWriter *jit);
|
|
|
|
/**
|
|
* Writes the Sysreq.* opcodes as a function call.
|
|
*/
|
|
void WriteOp_Sysreq_C_Function(JitWriter *jit);
|
|
|
|
/**
|
|
* Write the GENARRAY intrinsic function.
|
|
*/
|
|
void WriteIntrinsic_GenArray(JitWriter *jit);
|
|
|
|
void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg);
|
|
|
|
/**
|
|
* Generates code to set an error state in the VM and return.
|
|
* This is used for generating the error set points in the VM.
|
|
* GetError writes the error from the context. SetError hardcodes.
|
|
*/
|
|
void Write_GetError(JitWriter *jit);
|
|
void Write_SetError(JitWriter *jit, int error);
|
|
|
|
/**
|
|
* Checks the stacks for min and low errors.
|
|
* :TODO: Should a variation of this go in the pushN opcodes?
|
|
*/
|
|
void Write_CheckStack_Min(JitWriter *jit);
|
|
void Write_CheckStack_Low(JitWriter *jit);
|
|
|
|
/**
|
|
* Checks the heap for min and low errors.
|
|
*/
|
|
void Write_CheckHeap_Min(JitWriter *jit);
|
|
void Write_CheckHeap_Low(JitWriter *jit);
|
|
|
|
/**
|
|
* Checks for division by zero.
|
|
*/
|
|
void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg);
|
|
|
|
/**
|
|
* Writes the break debug function.
|
|
*/
|
|
void Write_BreakDebug(JitWriter *jit);
|
|
|
|
/**
|
|
* These are for writing the PushN opcodes.
|
|
*/
|
|
void Macro_PushN_Addr(JitWriter *jit, int i);
|
|
void Macro_PushN_S(JitWriter *jit, int i);
|
|
void Macro_PushN_C(JitWriter *jit, int i);
|
|
void Macro_PushN(JitWriter *jit, int i);
|
|
|
|
/**
|
|
* Bound checking for the tracker stack,
|
|
*/
|
|
int JIT_VerifyLowBoundTracker(sp_context_t *ctx);
|
|
int JIT_VerifyOrAllocateTracker(sp_context_t *ctx);
|
|
|
|
/**
|
|
* Writes the push into tracker function.
|
|
*/
|
|
void WriteOp_Tracker_Push_Reg(JitWriter *jit, uint8_t reg);
|
|
|
|
/**
|
|
* Writes the rounding table for the float compare opcode.
|
|
*/
|
|
void Write_RoundingTable(JitWriter *jit);
|
|
|
|
/**
|
|
* Aligns the current code position to 16 bytes.
|
|
*/
|
|
void AlignMe(JitWriter *jit);
|
|
|
|
/**
|
|
* Legend for Statuses:
|
|
* ****** *** ********
|
|
* DONE -> code generation is done
|
|
* !GEN -> code generation is deliberate skipped because:
|
|
* (default): compiler does not generate
|
|
* DEPRECATED: this feature no longer exists/supported
|
|
* UNSUPPORTED: this opcode is not supported
|
|
* TODO: done in case needed
|
|
* VERIFIED -> code generation is checked as run-time working. prefixes:
|
|
* ! errors are not checked yet.
|
|
* - non-inline errors are not checked yet.
|
|
* ~ assumed checked because of related variation, but not actually checked
|
|
*/
|
|
|
|
typedef enum
|
|
{
|
|
OP_NONE, /* invalid opcode */
|
|
OP_LOAD_PRI, //!VERIFIED
|
|
OP_LOAD_ALT, //~!VERIFIED (load.pri)
|
|
OP_LOAD_S_PRI, //VERIFIED
|
|
OP_LOAD_S_ALT, //VERIFIED
|
|
OP_LREF_PRI, //VERIFIED
|
|
OP_LREF_ALT, //~VERIFIED
|
|
OP_LREF_S_PRI, //VERIFIED
|
|
OP_LREF_S_ALT, //~VERIFIED (lref.s.pri)
|
|
OP_LOAD_I, //VERIFIED
|
|
OP_LODB_I, //VERIFIED
|
|
OP_CONST_PRI, //VERIFIED
|
|
OP_CONST_ALT, //~VERIFIED (const.pri)
|
|
OP_ADDR_PRI, //VERIFIED
|
|
OP_ADDR_ALT, //VERIFIED
|
|
OP_STOR_PRI, //VERIFIED
|
|
OP_STOR_ALT, //~VERIFIED (stor.pri)
|
|
OP_STOR_S_PRI, //VERIFIED
|
|
OP_STOR_S_ALT, //~VERIFIED (stor.s.pri)
|
|
OP_SREF_PRI, //VERIFIED
|
|
OP_SREF_ALT, //~VERIFIED
|
|
OP_SREF_S_PRI, //VERIFIED
|
|
OP_SREF_S_ALT, //~VERIFIED (stor.s.alt)
|
|
OP_STOR_I, //VERIFIED
|
|
OP_STRB_I, //VERIFIED
|
|
OP_LIDX, //VERIFIED
|
|
OP_LIDX_B, //DONE
|
|
OP_IDXADDR, //VERIFIED
|
|
OP_IDXADDR_B, //DONE
|
|
OP_ALIGN_PRI, // !GEN :TODO: - only used for pack access, drop support in compiler first
|
|
OP_ALIGN_ALT, // !GEN :TODO: - only used for pack access, drop support in compiler first
|
|
OP_LCTRL, // !GEN
|
|
OP_SCTRL, // !GEN
|
|
OP_MOVE_PRI, //~VERIFIED (move.alt)
|
|
OP_MOVE_ALT, //VERIFIED
|
|
OP_XCHG, //DONE
|
|
OP_PUSH_PRI, //DONE
|
|
OP_PUSH_ALT, //DONE
|
|
OP_PUSH_R, // !GEN DEPRECATED
|
|
OP_PUSH_C, //VERIFIED
|
|
OP_PUSH, //DONE
|
|
OP_PUSH_S, //VERIFIED
|
|
OP_POP_PRI, //VERIFIED
|
|
OP_POP_ALT, //VERIFIED
|
|
OP_STACK, //VERIFIED
|
|
OP_HEAP, //VERIFIED
|
|
OP_PROC, //VERIFIED
|
|
OP_RET, // !GEN
|
|
OP_RETN, //VERIFIED
|
|
OP_CALL, //VERIFIED
|
|
OP_CALL_PRI, // !GEN
|
|
OP_JUMP, //VERIFIED
|
|
OP_JREL, // !GEN
|
|
OP_JZER, //VERIFIED
|
|
OP_JNZ, //DONE
|
|
OP_JEQ, //VERIFIED
|
|
OP_JNEQ, //VERIFIED
|
|
OP_JLESS, // !GEN
|
|
OP_JLEQ, // !GEN
|
|
OP_JGRTR, // !GEN
|
|
OP_JGEQ, // !GEN
|
|
OP_JSLESS, //VERIFIED
|
|
OP_JSLEQ, //VERIFIED
|
|
OP_JSGRTR, //VERIFIED
|
|
OP_JSGEQ, //VERIFIED
|
|
OP_SHL, //VERIFIED
|
|
OP_SHR, //VERIFIED (Note: operator >>>)
|
|
OP_SSHR, //VERIFIED (Note: operator >>)
|
|
OP_SHL_C_PRI, //DONE
|
|
OP_SHL_C_ALT, //DONE
|
|
OP_SHR_C_PRI, //DONE
|
|
OP_SHR_C_ALT, //DONE
|
|
OP_SMUL, //VERIFIED
|
|
OP_SDIV, //DONE
|
|
OP_SDIV_ALT, //VERIFIED
|
|
OP_UMUL, // !GEN
|
|
OP_UDIV, // !GEN
|
|
OP_UDIV_ALT, // !GEN
|
|
OP_ADD, //VERIFIED
|
|
OP_SUB, //DONE
|
|
OP_SUB_ALT, //VERIFIED
|
|
OP_AND, //VERIFIED
|
|
OP_OR, //VERIFIED
|
|
OP_XOR, //VERIFIED
|
|
OP_NOT, //VERIFIED
|
|
OP_NEG, //VERIFIED
|
|
OP_INVERT, //VERIFIED
|
|
OP_ADD_C, //VERIFIED
|
|
OP_SMUL_C, //VERIFIED
|
|
OP_ZERO_PRI, //VERIFIED
|
|
OP_ZERO_ALT, //~VERIFIED
|
|
OP_ZERO, //VERIFIED
|
|
OP_ZERO_S, //VERIFIED
|
|
OP_SIGN_PRI, //DONE
|
|
OP_SIGN_ALT, //DONE
|
|
OP_EQ, //VERIFIED
|
|
OP_NEQ, //VERIFIED
|
|
OP_LESS, // !GEN
|
|
OP_LEQ, // !GEN
|
|
OP_GRTR, // !GEN
|
|
OP_GEQ, // !GEN
|
|
OP_SLESS, //VERIFIED
|
|
OP_SLEQ, //VERIFIED
|
|
OP_SGRTR, //VERIFIED
|
|
OP_SGEQ, //VERIFIED
|
|
OP_EQ_C_PRI, //DONE
|
|
OP_EQ_C_ALT, //DONE
|
|
OP_INC_PRI, //VERIFIED
|
|
OP_INC_ALT, //~VERIFIED (inc.pri)
|
|
OP_INC, //VERIFIED
|
|
OP_INC_S, //VERIFIED
|
|
OP_INC_I, //VERIFIED
|
|
OP_DEC_PRI, //VERIFIED
|
|
OP_DEC_ALT, //~VERIFIED (dec.pri)
|
|
OP_DEC, //VERIFIED
|
|
OP_DEC_S, //VERIFIED
|
|
OP_DEC_I, //VERIFIED
|
|
OP_MOVS, //VERIFIED
|
|
OP_CMPS, // !GEN
|
|
OP_FILL, //VERIFIED
|
|
OP_HALT, //DONE
|
|
OP_BOUNDS, //VERIFIED
|
|
OP_SYSREQ_PRI, // !GEN
|
|
OP_SYSREQ_C, //VERIFIED
|
|
OP_FILE, // !GEN DEPRECATED
|
|
OP_LINE, // !GEN DEPRECATED
|
|
OP_SYMBOL, // !GEN DEPRECATED
|
|
OP_SRANGE, // !GEN DEPRECATED
|
|
OP_JUMP_PRI, // !GEN
|
|
OP_SWITCH, //VERIFIED
|
|
OP_CASETBL, //VERIFIED
|
|
OP_SWAP_PRI, //VERIFIED
|
|
OP_SWAP_ALT, //~VERIFIED (swap.alt)
|
|
OP_PUSH_ADR, //VERIFIED
|
|
OP_NOP, //VERIFIED (lol)
|
|
OP_SYSREQ_N, //VERIFIED
|
|
OP_SYMTAG, // !GEN DEPRECATED
|
|
OP_BREAK, //DONE
|
|
OP_PUSH2_C, //~VERIFIED (push3.c)
|
|
OP_PUSH2, //VERIFIED
|
|
OP_PUSH2_S, //VERIFIED
|
|
OP_PUSH2_ADR, //VERIFIED
|
|
OP_PUSH3_C, //VERIFIED
|
|
OP_PUSH3, //~VERIFIED (push2)
|
|
OP_PUSH3_S, //~VERIFIED (push2.s)
|
|
OP_PUSH3_ADR, //~VERIFIED (push2.adr)
|
|
OP_PUSH4_C, //~VERIFIED (push3.c)
|
|
OP_PUSH4, //~VERIFIED (push2)
|
|
OP_PUSH4_S, //~VERIFIED (push2.s)
|
|
OP_PUSH4_ADR, //~VERIFIED (push2.adr)
|
|
OP_PUSH5_C, //~VERIFIED (push3.c)
|
|
OP_PUSH5, //~VERIFIED (push2)
|
|
OP_PUSH5_S, //~VERIFIED (push2.s)
|
|
OP_PUSH5_ADR, //~VERIFIED (push2.adr)
|
|
OP_LOAD_BOTH, //VERIFIED
|
|
OP_LOAD_S_BOTH, //VERIFIED
|
|
OP_CONST, //VERIFIED
|
|
OP_CONST_S, //DONE
|
|
/* ----- */
|
|
OP_SYSREQ_D, // !GEN UNSUPPORT
|
|
OP_SYSREQ_ND, // !GEN UNSUPPORT
|
|
/* ----- */
|
|
OP_TRACKER_PUSH_C, //DONE
|
|
OP_TRACKER_POP_SETHEAP, //VERIFIED
|
|
OP_GENARRAY, //VERIFIED
|
|
OP_GENARRAY_Z, //-VERIFIED (not tested for 1D arrays)
|
|
OP_STRADJUST_PRI, //VERIFIED
|
|
OP_STACKADJUST, //:TODO: VERIFY
|
|
OP_ENDPROC, //VERIFIED
|
|
OP_FABS, //VERIFIED
|
|
OP_FLOAT, //VERIFIED
|
|
OP_FLOATADD, //VERIFIED
|
|
OP_FLOATSUB, //VERIFIED
|
|
OP_FLOATMUL, //VERIFIED
|
|
OP_FLOATDIV, //VERIFIED
|
|
OP_RND_TO_NEAREST, //VERIFIED
|
|
OP_RND_TO_FLOOR, //VERIFIED
|
|
OP_RND_TO_CEIL, //VERIFIED
|
|
OP_RND_TO_ZERO, //VERIFIED
|
|
OP_FLOATCMP, //VERIFIED
|
|
/* ----- */
|
|
OP_NUM_OPCODES
|
|
} OPCODE;
|
|
|
|
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_
|