From 225954a27c7495c7faeb02a23b56ca19ba4ab6a6 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 21 Aug 2014 22:16:07 -0700 Subject: [PATCH 1/2] Modernize the smx headers. --- public/sourcepawn/sp_vm_types.h | 37 ++- .../compiler}/sp_file_headers.h | 0 sourcepawn/include/smx/smx-headers.h | 164 +++++++++++ sourcepawn/include/smx/smx-v1-opcodes.h | 266 ++++++++++++++++++ sourcepawn/include/smx/smx-v1.h | 205 ++++++++++++++ sourcepawn/include/smx/smx-v2-opcodes.h | 128 +++++++++ sourcepawn/include/smx/smx-v2.h | 218 ++++++++++++++ sourcepawn/jit/AMBuilder | 3 + sourcepawn/jit/BaseRuntime.cpp | 7 +- sourcepawn/jit/engine2.cpp | 6 +- sourcepawn/jit/interpreter.cpp | 1 + sourcepawn/jit/jit_shared.h | 2 + sourcepawn/jit/opcodes.cpp | 1 + sourcepawn/jit/opcodes.h | 231 +-------------- sourcepawn/jit/sp_vm_basecontext.cpp | 4 +- sourcepawn/jit/sp_vm_engine.cpp | 1 - sourcepawn/jit/x86/jit_x86.cpp | 5 +- 17 files changed, 1029 insertions(+), 250 deletions(-) rename {public/sourcepawn => sourcepawn/compiler}/sp_file_headers.h (100%) create mode 100644 sourcepawn/include/smx/smx-headers.h create mode 100644 sourcepawn/include/smx/smx-v1-opcodes.h create mode 100644 sourcepawn/include/smx/smx-v1.h create mode 100644 sourcepawn/include/smx/smx-v2-opcodes.h create mode 100644 sourcepawn/include/smx/smx-v2.h diff --git a/public/sourcepawn/sp_vm_types.h b/public/sourcepawn/sp_vm_types.h index ba57ff6d..4dcfe4c1 100644 --- a/public/sourcepawn/sp_vm_types.h +++ b/public/sourcepawn/sp_vm_types.h @@ -36,8 +36,8 @@ * @file sp_vm_types.h * @brief Contains all run-time SourcePawn structures. */ - -#include "sp_file_headers.h" +#include +#include typedef uint32_t ucell_t; /**< Unsigned 32bit integer */ typedef int32_t cell_t; /**< Basic 32bit signed integer type for plugins */ @@ -189,10 +189,25 @@ typedef struct sp_debug_line_s uint32_t line; /**< Line number */ } sp_debug_line_t; -/** - * @brief These structures are equivalent. - */ -typedef sp_fdbg_arraydim_t sp_debug_arraydim_t; +// Occurs after an fdbg_symbol entry, for each dimension. +typedef struct sp_debug_arraydim_s +{ + int16_t tagid; /**< Tag id */ + uint32_t size; /**< Size of dimension */ +} sp_debug_arraydim_t; + +// Same as from . +typedef struct sp_debug_symbol_raw_s +{ + int32_t addr; /**< Address rel to DAT or stack frame */ + int16_t tagid; /**< Tag id */ + uint32_t codestart; /**< Start scope validity in code */ + uint32_t codeend; /**< End scope validity in code */ + uint8_t ident; /**< Variable type */ + uint8_t vclass; /**< Scope class (local vs global) */ + uint16_t dimcount; /**< Dimension count (for arrays) */ + uint32_t name; /**< Offset into debug nametable */ +} sp_debug_symbol_raw_t; /** * @brief The majority of this struct is already located in the parent @@ -200,11 +215,11 @@ typedef sp_fdbg_arraydim_t sp_debug_arraydim_t; */ typedef struct sp_debug_symbol_s { - uint32_t codestart; /**< Relocated code address */ - uint32_t codeend; /**< Relocated code end address */ - const char * name; /**< Relocated name */ - sp_debug_arraydim_t *dims; /**< Relocated dimension struct, if any */ - sp_fdbg_symbol_t *sym; /**< Pointer to original symbol */ + uint32_t codestart; /**< Relocated code address */ + uint32_t codeend; /**< Relocated code end address */ + const char * name; /**< Relocated name */ + sp_debug_arraydim_t *dims; /**< Relocated dimension struct, if any */ + sp_debug_symbol_raw_t *sym; /**< Pointer to original symbol */ } sp_debug_symbol_t; #endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H diff --git a/public/sourcepawn/sp_file_headers.h b/sourcepawn/compiler/sp_file_headers.h similarity index 100% rename from public/sourcepawn/sp_file_headers.h rename to sourcepawn/compiler/sp_file_headers.h diff --git a/sourcepawn/include/smx/smx-headers.h b/sourcepawn/include/smx/smx-headers.h new file mode 100644 index 00000000..dc9d7dcf --- /dev/null +++ b/sourcepawn/include/smx/smx-headers.h @@ -0,0 +1,164 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// 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 . +// +// 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 . + +#ifndef _INCLUDE_SPFILE_HEADERS_H +#define _INCLUDE_SPFILE_HEADERS_H + +#include +#include + +namespace sp { + +struct SmxConsts +{ + // SourcePawn File Format (SPFF) magic number. + static const uint32_t FILE_MAGIC = 0x53504646; + + // File format verison number. + // 0x0101 - Initial version used by spcomp1 and SourceMod 1.0. + // 0x0102 - Used by spcomp1 and SourceMod 1.1+. + // 0x0103 - Used by SourceMod 1.7+. + // 0x0200 - Used by spcomp2. + // + // The major version bits (8-15) indicate a product number. Consumers should + // reject any version for a different product. + // + // The minor version bits (0-7) indicate a compatibility revision. Any minor + // version higher than the current version should be rejected. + static const uint16_t SP1_VERSION_MIN = 0x0101; + static const uint16_t SP1_VERSION_MAX = 0x0103; + static const uint16_t SP2_VERSION_MIN = 0x0200; + static const uint16_t SP2_VERSION_MAX = 0x0200; + + // Compression types. + static const uint8_t FILE_COMPRESSION_NONE = 0; + static const uint8_t FILE_COMPRESSION_GZ = 1; + + // SourcePawn 1.0. + static const uint8_t CODE_VERSION_JIT1 = 9; + + // SourcePawn 1.1. + static const uint8_t CODE_VERSION_JIT2 = 10; + + // For SP1 consumers, the container version may not be checked, but usually + // the code version is. This constant allows newer containers to be rejected + // in those applications. + static const uint8_t CODE_VERSION_REJECT = 0x7F; +}; + +// These structures are byte-packed. +#if defined __GNUC__ +# pragma pack(1) +#else +# pragma pack(push) +# pragma pack(1) +#endif + +// The very first bytes in a .smx file. The .smx file format is a container for +// arbitrary sections, though to actually load a .smx file certain sections +// must be present. The on-disk format has four major regions, in order: +// 1. The header (sp_file_hdr_t). +// 2. The section list (sp_file_section_t). +// 3. The string table. +// 4. The section contents. +// +// Although any part of the file after the header can be compressed, by default +// only the section contents are, and the section list and string table are not. +typedef struct sp_file_hdr_s +{ + // Magic number and version number. + uint32_t magic; + uint16_t version; + + // Compression algorithm. If the file is not compressed, then imagesize and + // disksize are the same value, and dataoffs is 0. + // + // The start of the compressed region is indicated by dataoffs. The length + // of the compressed region is (disksize - dataoffs). The amount of memory + // required to hold the decompressed bytes is (imagesize - dataoffs). The + // compressed region should be expanded in-place. That is, bytes before + // "dataoffs" should be retained, and the decompressed region should be + // appended. + // + // |imagesize| is the amount of memory required to hold the entire container + // in memory. + // + // Note: This scheme may seem odd. It's a combination of historical debt and + // previously unspecified behavior. The original .amx file format contained + // an on-disk structure that supported an endian-agnostic variable-length + // encoding of its data section, and this structure was loaded directly into + // memory and used as the VM context. AMX Mod X later developed a container + // format called ".amxx" as a "universal binary" for 32-bit and 64-bit + // plugins. This format dropped compact encoding, but supported gzip. The + // disksize/imagesize oddness made its way to this file format. When .smx + // was created for SourceMod, it persisted even though AMX was dropped + // entirely. So it goes. + uint8_t compression; + uint32_t disksize; + uint32_t imagesize; + + // Number of named file sections. + uint8_t sections; + + // Offset to the string table. Each string is null-terminated. The string + // table is only used for strings related to parsing the container itself. + // For SourcePawn, a separate ".names" section exists for Pawn-specific data. + uint32_t stringtab; + + // Offset to where compression begins. + uint32_t dataoffs; +} sp_file_hdr_t; + +// Each section is written immediately after the header. +typedef struct sp_file_section_s +{ + uint32_t nameoffs; /**< Offset into the string table. */ + uint32_t dataoffs; /**< Offset into the file for the section contents. */ + uint32_t size; /**< Size of this section's contents. */ +} sp_file_section_t; + +// Code section. This is used only in SP1, but is emitted by default for legacy +// systems which check |codeversion| but not the SMX file version. +typedef struct sp_file_code_s +{ + uint32_t codesize; /**< Size of the code section. */ + uint8_t cellsize; /**< Cellsize in bytes. */ + uint8_t codeversion; /**< Version of opcodes supported. */ + uint16_t flags; /**< Flags. */ + uint32_t main; /**< Address to "main". */ + uint32_t code; /**< Offset to bytecode, relative to the start of this section. */ +} sp_file_code_t; + +#if defined __GNUC__ +# pragma pack() +#else +# pragma pack(pop) +#endif + +} // namespace sp + +#endif //_INCLUDE_SPFILE_HEADERS_H diff --git a/sourcepawn/include/smx/smx-v1-opcodes.h b/sourcepawn/include/smx/smx-v1-opcodes.h new file mode 100644 index 00000000..9ed2601d --- /dev/null +++ b/sourcepawn/include/smx/smx-v1-opcodes.h @@ -0,0 +1,266 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// Copyright (C) 2004-2014 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 . +// +// 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 . + +#ifndef _INCLUDE_SPFILE_HEADERS_v1_opcodes_H +#define _INCLUDE_SPFILE_HEADERS_v1_opcodes_H + +#include +#include + +namespace sp { + +// Opcodes labelled "UNGEN" cannot be generated by the compiler. Quite a few, +// if they could, make little sense in the context of a JIT and could not +// work anyway. Opcodes technically present in sc4.c/sc7.c (respectively, +// the code emitter and peephole optimizer) are not necessarily ever generated. +// For example, lref.pri and lref.alt would be used if a reference could be +// stored in the global scope; but they can't, so they are unreachable. +// +// Most opcodes have been manually verified. A few have not, as they are only +// produced by the peephole optimizer, or not produced at all, or eliminated +// during optimization. We generate them anyway, just in case, but they have +// not been tested. +// lref.s.alt (phopt only) +// stor.alt (never) +// stor.s.alt (never) +// sref.s.alt (never) +// lidx.b (phopt only, probably impossible) +// idxaddr.b (phopt only, looks difficult) +// move.pri (eliminated in phopt) +// shl.c.pri (eliminated in phopt) +// shl.c.alt (eliminated in phopt) +// shr.c.pri (eliminated in phopt) +// shr.c.alt (eliminated in phopt) +// eq.c.alt (never) +// inc.alt (never) +// dec.alt (never) +// sdiv (never) +// nop (never in function bodies) +// +// Additionally, some opcodes which were supported in the earlier JIT are no +// longer supported because of the above: +// lref.pri/alt +// sref.pri/alt +// sign.pri/alt + +#define OPCODE_LIST(_) \ + _(NONE, "none") \ + _(LOAD_PRI, "load.pri") \ + _(LOAD_ALT, "load.alt") \ + _(LOAD_S_PRI, "load.s.pri") \ + _(LOAD_S_ALT, "load.s.alt") \ + _(UNGEN_LREF_PRI, "lref.pri") \ + _(UNGEN_LREF_ALT, "lref.alt") \ + _(LREF_S_PRI, "lref.s.pri") \ + _(LREF_S_ALT, "lref.s.alt") \ + _(LOAD_I, "load.i") \ + _(LODB_I, "lodb.i") \ + _(CONST_PRI, "const.pri") \ + _(CONST_ALT, "const.alt") \ + _(ADDR_PRI, "addr.pri") \ + _(ADDR_ALT, "addr.alt") \ + _(STOR_PRI, "stor.pri") \ + _(STOR_ALT, "stor.alt") \ + _(STOR_S_PRI, "stor.s.pri") \ + _(STOR_S_ALT, "stor.s.alt") \ + _(UNGEN_SREF_PRI, "sref.pri") \ + _(UNGEN_SREF_ALT, "sref.alt") \ + _(SREF_S_PRI, "sref.s.pri") \ + _(SREF_S_ALT, "sref.s.alt") \ + _(STOR_I, "stor.i") \ + _(STRB_I, "strb.i") \ + _(LIDX, "lidx") \ + _(LIDX_B, "lidx.b") \ + _(IDXADDR, "idxaddr") \ + _(IDXADDR_B, "idxaddr.b") \ + _(UNGEN_ALIGN_PRI,"align.pri") \ + _(UNGEN_ALIGN_ALT,"align.alt") \ + _(UNGEN_LCTRL, "lctrl") \ + _(UNGEN_SCTRL, "sctrl") \ + _(MOVE_PRI, "move.pri") \ + _(MOVE_ALT, "move.alt") \ + _(XCHG, "xchg") \ + _(PUSH_PRI, "push.pri") \ + _(PUSH_ALT, "push.alt") \ + _(UNGEN_PUSH_R, "push.r") \ + _(PUSH_C, "push.c") \ + _(PUSH, "push") \ + _(PUSH_S, "push.s") \ + _(POP_PRI, "pop.pri") \ + _(POP_ALT, "pop.alt") \ + _(STACK, "stack") \ + _(HEAP, "heap") \ + _(PROC, "proc") \ + _(UNGEN_RET, "ret") \ + _(RETN, "retn") \ + _(CALL, "call") \ + _(UNGEN_CALL_PRI, "call.pri") \ + _(JUMP, "jump") \ + _(UNGEN_JREL, "jrel") \ + _(JZER, "jzer") \ + _(JNZ, "jnz") \ + _(JEQ, "jeq") \ + _(JNEQ, "jneq") \ + _(UNGEN_JLESS, "jsless") \ + _(UNGEN_JLEQ, "jleq") \ + _(UNGEN_JGRTR, "jgrtr") \ + _(UNGEN_JGEQ, "jgeq") \ + _(JSLESS, "jsless") \ + _(JSLEQ, "jsleq") \ + _(JSGRTR, "jsgrtr") \ + _(JSGEQ, "jsgeq") \ + _(SHL, "shl") \ + _(SHR, "shr") \ + _(SSHR, "sshr") \ + _(SHL_C_PRI, "shl.c.pri") \ + _(SHL_C_ALT, "shl.c.alt") \ + _(SHR_C_PRI, "shr.c.pri") \ + _(SHR_C_ALT, "shr.c.alt") \ + _(SMUL, "smul") \ + _(SDIV, "sdiv") \ + _(SDIV_ALT, "sdiv.alt") \ + _(UNGEN_UMUL, "umul") \ + _(UNGEN_UDIV, "udiv") \ + _(UNGEN_UDIV_ALT, "udiv.alt") \ + _(ADD, "add") \ + _(SUB, "sub") \ + _(SUB_ALT, "sub.alt") \ + _(AND, "and") \ + _(OR, "or") \ + _(XOR, "xor") \ + _(NOT, "not") \ + _(NEG, "neg") \ + _(INVERT, "invert") \ + _(ADD_C, "add.c") \ + _(SMUL_C, "smul.c") \ + _(ZERO_PRI, "zero.pri") \ + _(ZERO_ALT, "zero.alt") \ + _(ZERO, "zero") \ + _(ZERO_S, "zero.s") \ + _(UNGEN_SIGN_PRI, "sign.pri") \ + _(UNGEN_SIGN_ALT, "sign.alt") \ + _(EQ, "eq") \ + _(NEQ, "neq") \ + _(UNGEN_LESS, "less") \ + _(UNGEN_LEQ, "leq") \ + _(UNGEN_GRTR, "grtr") \ + _(UNGEN_GEQ, "geq") \ + _(SLESS, "sless") \ + _(SLEQ, "sleq") \ + _(SGRTR, "sgrtr") \ + _(SGEQ, "sgeq") \ + _(EQ_C_PRI, "eq.c.pri") \ + _(EQ_C_ALT, "eq.c.alt") \ + _(INC_PRI, "inc.pri") \ + _(INC_ALT, "inc.alt") \ + _(INC, "inc") \ + _(INC_S, "inc.s") \ + _(INC_I, "inc.i") \ + _(DEC_PRI, "dec.pri") \ + _(DEC_ALT, "dec.alt") \ + _(DEC, "dec") \ + _(DEC_S, "dec.s") \ + _(DEC_I, "dec.i") \ + _(MOVS, "movs") \ + _(UNGEN_CMPS, "cmps") \ + _(FILL, "fill") \ + _(HALT, "halt") \ + _(BOUNDS, "bounds") \ + _(UNGEN_SYSREQ_PRI,"sysreq.pri") \ + _(SYSREQ_C, "sysreq.c") \ + _(UNGEN_FILE, "file") \ + _(UNGEN_LINE, "line") \ + _(UNGEN_SYMBOL, "symbol") \ + _(UNGEN_SRANGE, "srange") \ + _(UNGEN_JUMP_PRI, "jump.pri") \ + _(SWITCH, "switch") \ + _(CASETBL, "casetbl") \ + _(SWAP_PRI, "swap.pri") \ + _(SWAP_ALT, "swap.alt") \ + _(PUSH_ADR, "push.adr") \ + _(NOP, "nop") \ + _(SYSREQ_N, "sysreq.n") \ + _(UNGEN_SYMTAG, "symtag") \ + _(BREAK, "break") \ + _(PUSH2_C, "push2.c") \ + _(PUSH2, "push2") \ + _(PUSH2_S, "push2.s") \ + _(PUSH2_ADR, "push2.adr") \ + _(PUSH3_C, "push3.c") \ + _(PUSH3, "push3") \ + _(PUSH3_S, "push3.s") \ + _(PUSH3_ADR, "push3.adr") \ + _(PUSH4_C, "push4.c") \ + _(PUSH4, "push4") \ + _(PUSH4_S, "push4.s") \ + _(PUSH4_ADR, "push4.adr") \ + _(PUSH5_C, "push5.c") \ + _(PUSH5, "push5") \ + _(PUSH5_S, "push5.s") \ + _(PUSH5_ADR, "push5.adr") \ + _(LOAD_BOTH, "load.both") \ + _(LOAD_S_BOTH, "load.s.both") \ + _(CONST, "const") \ + _(CONST_S, "const.s") \ + _(UNGEN_SYSREQ_D, "sysreq.d") \ + _(UNGEB_SYSREQ_ND,"sysreq.nd") \ + _(TRACKER_PUSH_C, "trk.push.c") \ + _(TRACKER_POP_SETHEAP,"trk.pop") \ + _(GENARRAY, "genarray") \ + _(GENARRAY_Z, "genarray.z") \ + _(STRADJUST_PRI, "stradjust.pri") \ + _(UNGEN_STKADJUST,"stackadjust") \ + _(ENDPROC, "endproc") \ + _(FABS, "fabs") \ + _(FLOAT, "float") \ + _(FLOATADD, "float.add") \ + _(FLOATSUB, "float.sub") \ + _(FLOATMUL, "float.mul") \ + _(FLOATDIV, "float.div") \ + _(RND_TO_NEAREST, "round") \ + _(RND_TO_FLOOR, "floor") \ + _(RND_TO_CEIL, "ceil") \ + _(RND_TO_ZERO, "rndtozero") \ + _(FLOATCMP, "float.cmp") \ + _(FLOAT_GT, "float.gt") \ + _(FLOAT_GE, "float.ge") \ + _(FLOAT_LT, "float.lt") \ + _(FLOAT_LE, "float.le") \ + _(FLOAT_NE, "float.ne") \ + _(FLOAT_EQ, "float.eq") \ + _(FLOAT_NOT, "float.not") + +enum OPCODE { +#define _(op, text) OP_##op, + OPCODE_LIST(_) +#undef _ + OPCODES_TOTAL +}; + +} // namespace sp + +#endif // _INCLUDE_SPFILE_HEADERS_v1_opcodes_H diff --git a/sourcepawn/include/smx/smx-v1.h b/sourcepawn/include/smx/smx-v1.h new file mode 100644 index 00000000..3ae95029 --- /dev/null +++ b/sourcepawn/include/smx/smx-v1.h @@ -0,0 +1,205 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// Copyright (C) 2004-2014 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 . +// +// 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 . + +#ifndef _INCLUDE_SPFILE_HEADERS_v1_H +#define _INCLUDE_SPFILE_HEADERS_v1_H + +#include +#include +#include + +namespace sp { + +// These structures are byte-packed. +#if defined __GNUC__ +# pragma pack(1) +#else +# pragma pack(push) +# pragma pack(1) +#endif + +// (Obsolete) debug-information is present. +static const uint16_t CODEFLAG_DEBUG = 0x1; + +// The ".data" section. +typedef struct sp_file_data_s +{ + uint32_t datasize; /**< Size of data section in memory */ + uint32_t memsize; /**< Total mem required (includes data) */ + uint32_t data; /**< File offset to data (helper) */ +} sp_file_data_t; + +// The ".publics" section. +typedef struct sp_file_publics_s +{ + uint32_t address; /**< Address relative to code section */ + uint32_t name; /**< Index into nametable */ +} sp_file_publics_t; + +// The ".natives" section. +typedef struct sp_file_natives_s +{ + uint32_t name; /**< Index into nametable */ +} sp_file_natives_t; + +// The ".pubvars" section. +typedef struct sp_file_pubvars_s +{ + uint32_t address; /**< Address relative to the DAT section */ + uint32_t name; /**< Index into nametable */ +} sp_file_pubvars_t; + +// The ".tags" section. +typedef struct sp_file_tag_s +{ + uint32_t tag_id; /**< Tag ID from compiler */ + uint32_t name; /**< Index into nametable */ +} sp_file_tag_t; + +// The ".dbg.info" section. +typedef struct sp_fdbg_info_s +{ + uint32_t num_files; /**< number of files */ + uint32_t num_lines; /**< number of lines */ + uint32_t num_syms; /**< number of symbols */ + uint32_t num_arrays; /**< number of symbols which are arrays */ +} sp_fdbg_info_t; + +// The ".dbg.files" section. +typedef struct sp_fdbg_file_s +{ + uint32_t addr; /**< Address into code */ + uint32_t name; /**< Offset into debug nametable */ +} sp_fdbg_file_t; + +// The ".dbg.lines" section. +typedef struct sp_fdbg_line_s +{ + uint32_t addr; /**< Address into code */ + uint32_t line; /**< Line number */ +} sp_fdbg_line_t; + +static const uint8_t IDENT_VARIABLE = 1; // Scalar local variable. +static const uint8_t IDENT_REFERENCE = 2; // Reference to a scalar argument. +static const uint8_t IDENT_ARRAY = 3; // Array with known dimensions. +static const uint8_t IDENT_REFARRAY = 4; // Array with unknown dimensions. +static const uint8_t IDENT_FUNCTION = 9; // Symbolic function. +static const uint8_t IDENT_VARARGS = 11; // Variadic argument (...). + +// The ".dbg.symbols" table. +typedef struct sp_fdbg_symbol_s +{ + int32_t addr; /**< Address rel to DAT or stack frame */ + int16_t tagid; /**< Tag id */ + uint32_t codestart; /**< Start scope validity in code */ + uint32_t codeend; /**< End scope validity in code */ + uint8_t ident; /**< Variable type */ + uint8_t vclass; /**< Scope class (local vs global) */ + uint16_t dimcount; /**< Dimension count (for arrays) */ + uint32_t name; /**< Offset into debug nametable */ +} sp_fdbg_symbol_t; + +// Occurs after an fdbg_symbol entry, for each dimension. +typedef struct sp_fdbg_arraydim_s +{ + int16_t tagid; /**< Tag id */ + uint32_t size; /**< Size of dimension */ +} sp_fdbg_arraydim_t; + +// Typedef for the ".names" section. +typedef char * sp_file_nametab_t; + +// Header for the ".dbg.natives" section. It is followed by a number of +// sp_fdbg_native_t entries. +typedef struct sp_fdbg_ntvtab_s +{ + uint32_t num_entries; /**< Number of entries. */ +} sp_fdbg_ntvtab_t; + +// An entry in the .dbg.natives section. Each is followed by an +// sp_fdbg_ntvarg_t for each argument. +typedef struct sp_fdbg_native_s +{ + uint32_t index; /**< Native index in the plugin. */ + uint32_t name; /**< Offset into debug nametable. */ + int16_t tagid; /**< Return tag. */ + uint16_t nargs; /**< Number of formal arguments. */ +} sp_fdbg_native_t; + +static const uint8_t IDENT_NATIVE_VARARGS = 1; + +// Each entry is followed by an sp_fdbg_arraydim_t for each dimcount. +typedef struct sp_fdbg_ntvarg_s +{ + uint8_t ident; /**< Variable type */ + int16_t tagid; /**< Tag id */ + uint16_t dimcount; /**< Dimension count (for arrays) */ + uint32_t name; /**< Offset into debug nametable */ +} sp_fdbg_ntvarg_t; + +#if defined __GNUC__ +# pragma pack() /* reset default packing */ +#else +# pragma pack(pop) /* reset previous packing */ +#endif + +// The packing for files changed by accident for a small window of time, and +// some files may have unparsable debug information using sp_fdbg_arraydim_t or +// sp_fdbg_symbol_t. +// +// If the file version is >= 0x0102, all structures will be packed. If the +// file version is < 0x0101, and the ".dbg.natives" table is present, +// all structures will be packed. +// +// If the version is 0x0101 and ".dbg.natives" is not present, then you must +// use the unpacked versions of those structures below. There is an extremely +// small chance, if the plugin used no natives, that the packing is +// indeterminate. This case is unlikely to be interesting, but if such a file +// exists, the only solution is to re-parse if the data looks corrupt. + +typedef struct sp_u_fdbg_arraydim_s +{ + int16_t tagid; /**< Tag id */ + uint32_t size; /**< Size of dimension */ +} sp_u_fdbg_arraydim_t; + +typedef struct sp_u_fdbg_symbol_s +{ + int32_t addr; /**< Address rel to DAT or stack frame */ + int16_t tagid; /**< Tag id */ + uint32_t codestart; /**< Start scope validity in code */ + uint32_t codeend; /**< End scope validity in code */ + uint8_t ident; /**< Variable type */ + uint8_t vclass; /**< Scope class (local vs global) */ + uint16_t dimcount; /**< Dimension count (for arrays) */ + uint32_t name; /**< Offset into debug nametable */ +} sp_u_fdbg_symbol_t; + +} // namespace sp + +#endif //_INCLUDE_SPFILE_HEADERS_v1_H + diff --git a/sourcepawn/include/smx/smx-v2-opcodes.h b/sourcepawn/include/smx/smx-v2-opcodes.h new file mode 100644 index 00000000..d75644c1 --- /dev/null +++ b/sourcepawn/include/smx/smx-v2-opcodes.h @@ -0,0 +1,128 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// Copyright (C) 2004-2014 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 . +// +// 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 . + +#ifndef _include_spfile_headers_v2_opcodes_h_ +#define _include_spfile_headers_v2_opcodes_h_ + +namespace sp { + +// Opcode definitions: +// number symbol name pops pushes length flags +OPDEF(0x00, NOP, "nop", 0, 0, 1, 0) + +// Basic stack ops. +OPDEF(0x01, POP, "pop", 1, 0, 1, 0) +OPDEF(0x02, PUSH_TRUE, "push.true", 0, 1, 1, 0) +OPDEF(0x03, PUSH_FALSE, "push.false", 0, 1, 1, 0) +OPDEF(0x04, PUSH_NULL, "push.null", 0, 1, 1, 0) +OPDEF(0x05, PUSH_I8, "push.i8", 0, 1, 2, 0) +OPDEF(0x06, PUSH_I32, "push.i32", 0, 1, 5, 0) +OPDEF(0x07, PUSH_I64, "push.i64", 0, 1, 9, 0) +ODPEF(0x08, PUSH_F32, "push.f32", 0, 1, 5, 0) +OPDEF(0x09, PUSH_F64, "push.f64", 0, 1, 9, 0) +OPDEF(0x0A, PUSH_STR, "push.s", 0, 1, 5, 0) + +// Get/set local variables. +OPDEF(0x10, GETLOCAL, "getlocal", 0, 1, 2, 0) +OPDEF(0x11, GETLOCAL_W, "getlocal.w", 0, 1, 3, 0) +OPDEF(0x12, GETLOCAL_0, "getlocal.0", 0, 1, 1, 0) +OPDEF(0x13, GETLOCAL_1, "getlocal.1", 0, 1, 1, 0) +OPDEF(0x14, GETLOCAL_2, "getlocal.2", 0, 1, 1, 0) +OPDEF(0x15, GETLOCAL_3, "getlocal.3", 0, 1, 1, 0) +OPDEF(0x18, SETLOCAL, "setlocal", 1, 0, 2, 0) +OPDEF(0x19, SETLOCAL_W, "setlocal.w", 1, 0, 3, 0) +OPDEF(0x1A, SETLOCAL_0, "setlocal.0", 1, 0, 1, 0) +OPDEF(0x1B, SETLOCAL_1, "setlocal.1", 1, 0, 1, 0) +OPDEF(0x1C, SETLOCAL_2, "setlocal.2", 1, 0, 1, 0) +OPDEF(0x1D, SETLOCAL_3, "setlocal.3", 1, 0, 1, 0) + +// Local variable references. +OPDEF(0x1E, REFLOCAL, "reflocal", 0, 1, 3, 0) +OPDEF(0x1F, LDREF, "ldref", 1, 1, 1, 0) +OPDEF(0x20, STREF, "stref", 1, 0, 1, 0) + +// Math operators. +OPDEF(0x40, ADD, "add", 2, 1, 1, 0) +OPDEF(0x41, SUB, "sub", 2, 1, 1, 0) +OPDEF(0x42, MUL, "mul", 2, 1, 1, 0) +OPDEF(0x43, DIV, "div", 2, 1, 1, 0) +OPDEF(0x44, MOD, "mod", 2, 1, 1, 0) +OPDEF(0x45, NEG, "neg", 1, 1, 1, 0) +OPDEF(0x46, SHR, "shr", 2, 1, 1, 0) +OPDEF(0x47, USHR, "ushr", 2, 1, 1, 0) +OPDEF(0x48, SHL, "shl", 2, 1, 1, 0) +OPDEF(0x49, BITOR, "bitor", 2, 1, 1, 0) +OPDEF(0x4A, BITAND, "bitand", 2, 1, 1, 0) +OPDEF(0x4B, BITXOR, "bitxor", 2, 1, 1, 0) +OPDEF(0x4C, BITNOT, "bitnot", 1, 1, 1, 0) + +// Logical operators. +OPDEF(0x60, AND, "and", 2, 1, 1, 0) +OPDEF(0x61, OR, "or", 2, 1, 1, 0) +OPDEF(0x62, NOT, "not", 1, 1, 1, 0) +OPDEF(0x63, LT, "lt", 2, 1, 1, 0) +OPDEF(0x64, LE, "le", 2, 1, 1, 0) +OPDEF(0x65, GT, "gt", 2, 1, 1, 0) +OPDEF(0x66, GE, "ge", 2, 1, 1, 0) +OPDEF(0x67, EQ, "eq", 2, 1, 1, 0) +OPDEF(0x68, NE, "ne", 2, 1, 1, 0) + +// Branching operators. +OPDEF(0x70, JUMP, "jump", 0, 0, 1, 0) +OPDEF(0x71, JT, "jt", 1, 0, 1, 0) +OPDEF(0x72, JF, "jf", 1, 0, 1, 0) +OPDEF(0x73, JLT, "jlt", 2, 0, 1, 0) +OPDEF(0x74, JLE, "jle", 2, 0, 1, 0) +OPDEF(0x75, JGT, "jgt", 2, 0, 1, 0) +OPDEF(0x76, JGE, "jge", 2, 0, 1, 0) +OPDEF(0x77, JEQ, "jeq", 2, 0, 1, 0) +OPDEF(0x78, JNE, "jne", 2, 0, 1, 0) + +// Function calling. +// +// The low 4 bits of the index for OP_CALL and OP_CALL_A indicate the type +// of call: +// 0000 - 0x0 : Invoke a method constant such as a native or global function. +// Bits 4-31 are an index into the .methods table. +// +// Call is followed by a method identifier. +OPDEF(0x90, CALL, "call", -1, -1, 5, 0) +// Same as call.a but followed with a variadic argument count. +OPDEF(0x91, CALL_A, "call.a", -1, -1, 9, 0) + +// Array has a typeid and pops a length off the stack. +OPDEF(0x96, ARRAY, "newarray", 1, 1, 5, 0) +// Fixedarray has an offset into the .types table. +OPDEF(0x97, FIXEDARRAY, "fixedarray", 0, 1, 5, 0) + +// Advanced stack operations. +OPDEF(0xB0, DUP, "dup", 1, 2, 1, 0) + + +} // namespace sp + +#endif // _include_spfile_headers_v2_opcodes_h_ diff --git a/sourcepawn/include/smx/smx-v2.h b/sourcepawn/include/smx/smx-v2.h new file mode 100644 index 00000000..9b8dec22 --- /dev/null +++ b/sourcepawn/include/smx/smx-v2.h @@ -0,0 +1,218 @@ +// vim: set sts=2 ts=8 sw=2 tw=99 et: +// ============================================================================= +// SourcePawn +// Copyright (C) 2004-2014 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 . +// +// 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 . + +#ifndef _INCLUDE_SPFILE_HEADERS_v2_H +#define _INCLUDE_SPFILE_HEADERS_v2_H + +#include + +namespace sp { + +// These structures are byte-packed. +#if defined __GNUC__ +# pragma pack(1) +#else +# pragma pack(push) +# pragma pack(1) +#endif + +// Tables present in smx v2: +// .names Blob of null-terminated strings. +// .methods Table of smx_method_t entries. +// .pcode Blob of smx_pcode_header_t entries. +// .globals Table of smx_global_var_t entries. +// .types Blob of type information. + +// TypeSpec is a variable-length encoding referenced anywhere that "typespec" +// is specified. +// +// Whenever a TypeSpec is referenced from outside the .types table, specifically +// as a "typeid", it has an encoding to save space: If the id is < 0x20, then +// the id is a single-byte TypeSpec. Otherwise, the |id - 0x20| is an offset +// into the .types section. +enum class TypeSpec : uint8_t +{ + // The void type is special in that it is not a storable type. + void_t = 0x0, + + // Standard C++ datatypes. + boolean = 0x1, + RESERVED_int8 = 0x2, + RESERVED_uint8 = 0x3, + RESERVED_int16 = 0x4, + RESERVED_uint16 = 0x5, + int32 = 0x6, + RESERVED_uint32 = 0x7, + RESERVED_int64 = 0x8, + RESERVED_uint64 = 0x9, + + // platform-width int and uint. + RESERVED_intptr = 0xA, + RESERVED_uintptr = 0xB, + + float32 = 0xC, + RESERVED_float64 = 0xD, + + // char8 is semantically an alias for int8. + char8 = 0xE, + + RESERVED_char32 = 0xF, // Full unicode point. + + RESERVED_string = 0x16, // String reference. + RESERVED_object = 0x17, // Opaque object reference. + + // Followed by an int32 index into the .classes table. + RESERVED_classdef = 0x40, + + // Followed by an int32 index into the .structs table. + RESERVED_structdef = 0x41, + + // Followed by: + // [int8 formalCount] ; Number of formal parameters, counting varargs. + // [typespec *formals] ; Sequence of formal parameter specifications. + // + // When the type spec is for a method definition (for example, the .method + // table), then each type in |formals| must begin with "named" (0x7e) or, + // if it is the last formal, may be "variadic" (0x7a). + method = 0x50, + + // Fixed arrays have their size as part of their type, are copied by-value, + // and passed by-reference. + // + // Followed by: + // typespec type ; Type specification of innermost elements. + // uint8 rank ; Number of dimensions + // int32* dims ; One dimension for each rank. + fixedarray = 0x60, + + // Arrays are true arrays. They are copied by-reference and passed by- + // reference. + // + // Followed by: + // typesec type ; Type specification of innermost elements. + // uint8 rank ; Number of dimensions. + RESERVED_array = 0x61, + + // Only legal as the initial byte or byte following "named" (0x7e) in a + // parameter for a method signature. + // + // Followed by a typespec. Only typespecs < 0x60 ar elegal. + byref = 0x70, + + // Only legal as the initial byte or byte following "named" (0x7e) in a + // parameter for a method signature. + // + // Followed by a typespec. + variadic = 0x7A, + + // Only legal as the initial byte in a parameter or local variable signature. + // + // Followed by: + // uint32 name ; Index into the .names section. + // typespec type ; Type. + named = 0x7E, + + // For readability, this may be emitted at the end of typespec lists. It must + // not be emitted at the end of nested typespecs. + terminator = 0x7F +}; + +// Flags for method definitions. +enum class MethodFlags : uint32_t +{ + STATIC = 0x1, + VARIADIC = 0x2, + PUBLIC = 0x4, + NATIVE = 0x8, + OPTIONAL = 0x10 +}; + +// Specifies an entry in the .methods table. +struct smx_method_t +{ + // Offset into the .names section. + uint32_t name; + + MethodFlags flags; + + // Offset into .types, which must point at a TypeSpec::method. + uint32_t typespec; + + // Offset into .pcode. If flags contains NATIVE, this must be 0. + uint32_t address; +}; + +enum class GlobalVarFlags : uint32_t +{ + PUBLIC = 0x04, + CONST = 0x08 +}; + +// Specifies an entry in the .globals table. +struct smx_global_var_t +{ + // Offset into the .names section. + uint32_t name; + + GlobalVarFlags flags; + + // TypeId of the global. + uint32_t type_id; +}; + +// Specifies the layout we expect at a valid pcode starting position. +struct smx_pcode_header_t +{ + // Must be 0. + uint32_t reserved; + + // Number of local variables. + uint16_t nlocals; + + // Maximum depth of the operand stack. + uint16_t max_depth; + + // Pointer to .types section where local information begins. + uint32_t local_specs; + + // Number of bytes of pcode in the method. + uint32_t length; +}; + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// DO NOT DEFINE NEW STRUCTURES BELOW. +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +#if defined __GNUC__ +# pragma pack() +#else +# pragma pack(pop) +#endif + +} // namespace sp + +#endif // _INCLUDE_SPFILE_HEADERS_v2_H diff --git a/sourcepawn/jit/AMBuilder b/sourcepawn/jit/AMBuilder index 77c3cdfd..a09b49c0 100644 --- a/sourcepawn/jit/AMBuilder +++ b/sourcepawn/jit/AMBuilder @@ -12,6 +12,9 @@ binary.compiler.includes += [ os.path.join(builder.sourcePath, 'public', 'jit'), os.path.join(builder.sourcePath, 'public', 'jit', 'x86'), os.path.join(builder.sourcePath, 'knight', 'shared'), + + # The include path for SP v2 stuff. + os.path.join(builder.sourcePath, 'sourcepawn', 'include'), ] if builder.target_platform == 'linux': diff --git a/sourcepawn/jit/BaseRuntime.cpp b/sourcepawn/jit/BaseRuntime.cpp index c7d5ec02..fcf7fbf7 100644 --- a/sourcepawn/jit/BaseRuntime.cpp +++ b/sourcepawn/jit/BaseRuntime.cpp @@ -11,6 +11,7 @@ #include "md5/md5.h" +using namespace sp; using namespace SourcePawn; static inline bool @@ -171,9 +172,9 @@ int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base) if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) { sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs); - if (cod->codeversion < SP_CODEVERS_JIT1) + if (cod->codeversion < SmxConsts::CODE_VERSION_JIT1) return SP_ERROR_CODE_TOO_OLD; - if (cod->codeversion > SP_CODEVERS_JIT2) + if (cod->codeversion > SmxConsts::CODE_VERSION_JIT2) return SP_ERROR_CODE_TOO_NEW; m_plugin.pcode = base + secptr->dataoffs + cod->code; @@ -266,7 +267,7 @@ int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base) if (m_plugin.pcode == NULL || m_plugin.data == NULL) return SP_ERROR_FILE_FORMAT; - if ((m_plugin.flags & SP_FLAG_DEBUG) && ( + if ((m_plugin.flags & sp::CODEFLAG_DEBUG) && ( !(m_plugin.debug.files) || !(m_plugin.debug.lines) || !(m_plugin.debug.symbols) || diff --git a/sourcepawn/jit/engine2.cpp b/sourcepawn/jit/engine2.cpp index 9ce845cb..e5a8b8c2 100644 --- a/sourcepawn/jit/engine2.cpp +++ b/sourcepawn/jit/engine2.cpp @@ -37,7 +37,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file /* Rewind for safety */ fread(&hdr, sizeof(sp_file_hdr_t), 1, fp); - if (hdr.magic != SPFILE_MAGIC) + if (hdr.magic != SmxConsts::FILE_MAGIC) { error = SP_ERROR_FILE_FORMAT; goto return_error; @@ -45,7 +45,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file switch (hdr.compression) { - case SPFILE_COMPRESSION_GZ: + case SmxConsts::FILE_COMPRESSION_GZ: { uint32_t uncompsize = hdr.imagesize - hdr.dataoffs; uint32_t compsize = hdr.disksize - hdr.dataoffs; @@ -77,7 +77,7 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file free(uncompdata); break; } - case SPFILE_COMPRESSION_NONE: + case SmxConsts::FILE_COMPRESSION_NONE: { base = (uint8_t *)malloc(hdr.imagesize); rewind(fp); diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 257e9414..fcaafe61 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -22,6 +22,7 @@ #define STACK_MARGIN 64 +using namespace sp; using namespace SourcePawn; static inline bool diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 4642e5dd..4e06b61e 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -3,7 +3,9 @@ #define _INCLUDE_SOURCEPAWN_JIT_SHARED_H_ #include +#include +using namespace sp; using namespace SourcePawn; #define SP_MAX_RETURN_STACK 1024 diff --git a/sourcepawn/jit/opcodes.cpp b/sourcepawn/jit/opcodes.cpp index ef50eacf..c2cf3eb9 100644 --- a/sourcepawn/jit/opcodes.cpp +++ b/sourcepawn/jit/opcodes.cpp @@ -31,6 +31,7 @@ #include "opcodes.h" #include "jit_shared.h" +using namespace sp; using namespace SourcePawn; const char *OpcodeNames[] = { diff --git a/sourcepawn/jit/opcodes.h b/sourcepawn/jit/opcodes.h index 599b0353..ac70f4cc 100644 --- a/sourcepawn/jit/opcodes.h +++ b/sourcepawn/jit/opcodes.h @@ -32,235 +32,10 @@ #ifndef _INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_ #define _INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_ -#include +#include +#include "jit_shared.h" -// Opcodes labelled "UNGEN" cannot be generated by the compiler. Quite a few, -// if they could, make little sense in the context of a JIT and could not -// work anyway. Opcodes technically present in sc4.c/sc7.c (respectively, -// the code emitter and peephole optimizer) are not necessarily ever generated. -// For example, lref.pri and lref.alt would be used if a reference could be -// stored in the global scope; but they can't, so they are unreachable. -// -// Most opcodes have been manually verified. A few have not, as they are only -// produced by the peephole optimizer, or not produced at all, or eliminated -// during optimization. We generate them anyway, just in case, but they have -// not been tested. -// lref.s.alt (phopt only) -// stor.alt (never) -// stor.s.alt (never) -// sref.s.alt (never) -// lidx.b (phopt only, probably impossible) -// idxaddr.b (phopt only, looks difficult) -// move.pri (eliminated in phopt) -// shl.c.pri (eliminated in phopt) -// shl.c.alt (eliminated in phopt) -// shr.c.pri (eliminated in phopt) -// shr.c.alt (eliminated in phopt) -// eq.c.alt (never) -// inc.alt (never) -// dec.alt (never) -// sdiv (never) -// nop (never in function bodies) -// -// Additionally, some opcodes which were supported in the earlier JIT are no -// longer supported because of the above: -// lref.pri/alt -// sref.pri/alt -// sign.pri/alt - -#define OPCODE_LIST(_) \ - _(NONE, "none") \ - _(LOAD_PRI, "load.pri") \ - _(LOAD_ALT, "load.alt") \ - _(LOAD_S_PRI, "load.s.pri") \ - _(LOAD_S_ALT, "load.s.alt") \ - _(UNGEN_LREF_PRI, "lref.pri") \ - _(UNGEN_LREF_ALT, "lref.alt") \ - _(LREF_S_PRI, "lref.s.pri") \ - _(LREF_S_ALT, "lref.s.alt") \ - _(LOAD_I, "load.i") \ - _(LODB_I, "lodb.i") \ - _(CONST_PRI, "const.pri") \ - _(CONST_ALT, "const.alt") \ - _(ADDR_PRI, "addr.pri") \ - _(ADDR_ALT, "addr.alt") \ - _(STOR_PRI, "stor.pri") \ - _(STOR_ALT, "stor.alt") \ - _(STOR_S_PRI, "stor.s.pri") \ - _(STOR_S_ALT, "stor.s.alt") \ - _(UNGEN_SREF_PRI, "sref.pri") \ - _(UNGEN_SREF_ALT, "sref.alt") \ - _(SREF_S_PRI, "sref.s.pri") \ - _(SREF_S_ALT, "sref.s.alt") \ - _(STOR_I, "stor.i") \ - _(STRB_I, "strb.i") \ - _(LIDX, "lidx") \ - _(LIDX_B, "lidx.b") \ - _(IDXADDR, "idxaddr") \ - _(IDXADDR_B, "idxaddr.b") \ - _(UNGEN_ALIGN_PRI,"align.pri") \ - _(UNGEN_ALIGN_ALT,"align.alt") \ - _(UNGEN_LCTRL, "lctrl") \ - _(UNGEN_SCTRL, "sctrl") \ - _(MOVE_PRI, "move.pri") \ - _(MOVE_ALT, "move.alt") \ - _(XCHG, "xchg") \ - _(PUSH_PRI, "push.pri") \ - _(PUSH_ALT, "push.alt") \ - _(UNGEN_PUSH_R, "push.r") \ - _(PUSH_C, "push.c") \ - _(PUSH, "push") \ - _(PUSH_S, "push.s") \ - _(POP_PRI, "pop.pri") \ - _(POP_ALT, "pop.alt") \ - _(STACK, "stack") \ - _(HEAP, "heap") \ - _(PROC, "proc") \ - _(UNGEN_RET, "ret") \ - _(RETN, "retn") \ - _(CALL, "call") \ - _(UNGEN_CALL_PRI, "call.pri") \ - _(JUMP, "jump") \ - _(UNGEN_JREL, "jrel") \ - _(JZER, "jzer") \ - _(JNZ, "jnz") \ - _(JEQ, "jeq") \ - _(JNEQ, "jneq") \ - _(UNGEN_JLESS, "jsless") \ - _(UNGEN_JLEQ, "jleq") \ - _(UNGEN_JGRTR, "jgrtr") \ - _(UNGEN_JGEQ, "jgeq") \ - _(JSLESS, "jsless") \ - _(JSLEQ, "jsleq") \ - _(JSGRTR, "jsgrtr") \ - _(JSGEQ, "jsgeq") \ - _(SHL, "shl") \ - _(SHR, "shr") \ - _(SSHR, "sshr") \ - _(SHL_C_PRI, "shl.c.pri") \ - _(SHL_C_ALT, "shl.c.alt") \ - _(SHR_C_PRI, "shr.c.pri") \ - _(SHR_C_ALT, "shr.c.alt") \ - _(SMUL, "smul") \ - _(SDIV, "sdiv") \ - _(SDIV_ALT, "sdiv.alt") \ - _(UNGEN_UMUL, "umul") \ - _(UNGEN_UDIV, "udiv") \ - _(UNGEN_UDIV_ALT, "udiv.alt") \ - _(ADD, "add") \ - _(SUB, "sub") \ - _(SUB_ALT, "sub.alt") \ - _(AND, "and") \ - _(OR, "or") \ - _(XOR, "xor") \ - _(NOT, "not") \ - _(NEG, "neg") \ - _(INVERT, "invert") \ - _(ADD_C, "add.c") \ - _(SMUL_C, "smul.c") \ - _(ZERO_PRI, "zero.pri") \ - _(ZERO_ALT, "zero.alt") \ - _(ZERO, "zero") \ - _(ZERO_S, "zero.s") \ - _(UNGEN_SIGN_PRI, "sign.pri") \ - _(UNGEN_SIGN_ALT, "sign.alt") \ - _(EQ, "eq") \ - _(NEQ, "neq") \ - _(UNGEN_LESS, "less") \ - _(UNGEN_LEQ, "leq") \ - _(UNGEN_GRTR, "grtr") \ - _(UNGEN_GEQ, "geq") \ - _(SLESS, "sless") \ - _(SLEQ, "sleq") \ - _(SGRTR, "sgrtr") \ - _(SGEQ, "sgeq") \ - _(EQ_C_PRI, "eq.c.pri") \ - _(EQ_C_ALT, "eq.c.alt") \ - _(INC_PRI, "inc.pri") \ - _(INC_ALT, "inc.alt") \ - _(INC, "inc") \ - _(INC_S, "inc.s") \ - _(INC_I, "inc.i") \ - _(DEC_PRI, "dec.pri") \ - _(DEC_ALT, "dec.alt") \ - _(DEC, "dec") \ - _(DEC_S, "dec.s") \ - _(DEC_I, "dec.i") \ - _(MOVS, "movs") \ - _(UNGEN_CMPS, "cmps") \ - _(FILL, "fill") \ - _(HALT, "halt") \ - _(BOUNDS, "bounds") \ - _(UNGEN_SYSREQ_PRI,"sysreq.pri") \ - _(SYSREQ_C, "sysreq.c") \ - _(UNGEN_FILE, "file") \ - _(UNGEN_LINE, "line") \ - _(UNGEN_SYMBOL, "symbol") \ - _(UNGEN_SRANGE, "srange") \ - _(UNGEN_JUMP_PRI, "jump.pri") \ - _(SWITCH, "switch") \ - _(CASETBL, "casetbl") \ - _(SWAP_PRI, "swap.pri") \ - _(SWAP_ALT, "swap.alt") \ - _(PUSH_ADR, "push.adr") \ - _(NOP, "nop") \ - _(SYSREQ_N, "sysreq.n") \ - _(UNGEN_SYMTAG, "symtag") \ - _(BREAK, "break") \ - _(PUSH2_C, "push2.c") \ - _(PUSH2, "push2") \ - _(PUSH2_S, "push2.s") \ - _(PUSH2_ADR, "push2.adr") \ - _(PUSH3_C, "push3.c") \ - _(PUSH3, "push3") \ - _(PUSH3_S, "push3.s") \ - _(PUSH3_ADR, "push3.adr") \ - _(PUSH4_C, "push4.c") \ - _(PUSH4, "push4") \ - _(PUSH4_S, "push4.s") \ - _(PUSH4_ADR, "push4.adr") \ - _(PUSH5_C, "push5.c") \ - _(PUSH5, "push5") \ - _(PUSH5_S, "push5.s") \ - _(PUSH5_ADR, "push5.adr") \ - _(LOAD_BOTH, "load.both") \ - _(LOAD_S_BOTH, "load.s.both") \ - _(CONST, "const") \ - _(CONST_S, "const.s") \ - _(UNGEN_SYSREQ_D, "sysreq.d") \ - _(UNGEB_SYSREQ_ND,"sysreq.nd") \ - _(TRACKER_PUSH_C, "trk.push.c") \ - _(TRACKER_POP_SETHEAP,"trk.pop") \ - _(GENARRAY, "genarray") \ - _(GENARRAY_Z, "genarray.z") \ - _(STRADJUST_PRI, "stradjust.pri") \ - _(UNGEN_STKADJUST,"stackadjust") \ - _(ENDPROC, "endproc") \ - _(FABS, "fabs") \ - _(FLOAT, "float") \ - _(FLOATADD, "float.add") \ - _(FLOATSUB, "float.sub") \ - _(FLOATMUL, "float.mul") \ - _(FLOATDIV, "float.div") \ - _(RND_TO_NEAREST, "round") \ - _(RND_TO_FLOOR, "floor") \ - _(RND_TO_CEIL, "ceil") \ - _(RND_TO_ZERO, "rndtozero") \ - _(FLOATCMP, "float.cmp") \ - _(FLOAT_GT, "float.gt") \ - _(FLOAT_GE, "float.ge") \ - _(FLOAT_LT, "float.lt") \ - _(FLOAT_LE, "float.le") \ - _(FLOAT_NE, "float.ne") \ - _(FLOAT_EQ, "float.eq") \ - _(FLOAT_NOT, "float.not") - -enum OPCODE { -#define _(op, text) OP_##op, - OPCODE_LIST(_) -#undef _ - OPCODES_TOTAL -}; +typedef sp::OPCODE OPCODE; namespace SourcePawn { void SpewOpcode(const sp_plugin_t *plugin, cell_t *start, cell_t *cip); diff --git a/sourcepawn/jit/sp_vm_basecontext.cpp b/sourcepawn/jit/sp_vm_basecontext.cpp index b2e841ad..dbd4c1dd 100644 --- a/sourcepawn/jit/sp_vm_basecontext.cpp +++ b/sourcepawn/jit/sp_vm_basecontext.cpp @@ -738,7 +738,7 @@ int DebugInfo::LookupFunction(ucell_t addr, const char **name) { sym = (sp_fdbg_symbol_t *)cursor; - if (sym->ident == SP_SYM_FUNCTION + if (sym->ident == sp::IDENT_FUNCTION && sym->codestart <= addr && sym->codeend > addr) { @@ -769,7 +769,7 @@ int DebugInfo::LookupFunction(ucell_t addr, const char **name) { sym = (sp_u_fdbg_symbol_t *)cursor; - if (sym->ident == SP_SYM_FUNCTION + if (sym->ident == sp::IDENT_FUNCTION && sym->codestart <= addr && sym->codeend > addr) { diff --git a/sourcepawn/jit/sp_vm_engine.cpp b/sourcepawn/jit/sp_vm_engine.cpp index 05e5be15..4c314b20 100644 --- a/sourcepawn/jit/sp_vm_engine.cpp +++ b/sourcepawn/jit/sp_vm_engine.cpp @@ -34,7 +34,6 @@ #include #include "sp_vm_types.h" #include -#include "sp_file_headers.h" #include "sp_vm_engine.h" #include "zlib/zlib.h" #include "sp_vm_basecontext.h" diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index a0930ba9..26e4098f 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -40,6 +40,7 @@ #include "watchdog_timer.h" #include "interpreter.h" +using namespace sp; using namespace Knight; #if defined USE_UNGEN_OPCODES @@ -230,7 +231,7 @@ GetFunctionName(const sp_plugin_t *plugin, uint32_t offs) for (iter = 0; iter < max; iter++) { sym = (sp_fdbg_symbol_t *)cursor; - if (sym->ident == SP_SYM_FUNCTION && sym->codestart <= offs && sym->codeend > offs) + if (sym->ident == sp::IDENT_FUNCTION && sym->codestart <= offs && sym->codeend > offs) return plugin->debug.stringbase + sym->name; if (sym->dimcount > 0) { @@ -252,7 +253,7 @@ GetFunctionName(const sp_plugin_t *plugin, uint32_t offs) for (iter = 0; iter < max; iter++) { sym = (sp_u_fdbg_symbol_t *)cursor; - if (sym->ident == SP_SYM_FUNCTION && sym->codestart <= offs && sym->codeend > offs) + if (sym->ident == sp::IDENT_FUNCTION && sym->codestart <= offs && sym->codeend > offs) return plugin->debug.stringbase + sym->name; if (sym->dimcount > 0) { From 25241fa2788a46fa15f9f65fd2ca5fb068f4e919 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 21 Aug 2014 22:19:25 -0700 Subject: [PATCH 2/2] Remove file. --- sourcepawn/include/smx/smx-v2-opcodes.h | 128 ------------------------ 1 file changed, 128 deletions(-) delete mode 100644 sourcepawn/include/smx/smx-v2-opcodes.h diff --git a/sourcepawn/include/smx/smx-v2-opcodes.h b/sourcepawn/include/smx/smx-v2-opcodes.h deleted file mode 100644 index d75644c1..00000000 --- a/sourcepawn/include/smx/smx-v2-opcodes.h +++ /dev/null @@ -1,128 +0,0 @@ -// vim: set sts=2 ts=8 sw=2 tw=99 et: -// ============================================================================= -// SourcePawn -// Copyright (C) 2004-2014 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 . -// -// 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 . - -#ifndef _include_spfile_headers_v2_opcodes_h_ -#define _include_spfile_headers_v2_opcodes_h_ - -namespace sp { - -// Opcode definitions: -// number symbol name pops pushes length flags -OPDEF(0x00, NOP, "nop", 0, 0, 1, 0) - -// Basic stack ops. -OPDEF(0x01, POP, "pop", 1, 0, 1, 0) -OPDEF(0x02, PUSH_TRUE, "push.true", 0, 1, 1, 0) -OPDEF(0x03, PUSH_FALSE, "push.false", 0, 1, 1, 0) -OPDEF(0x04, PUSH_NULL, "push.null", 0, 1, 1, 0) -OPDEF(0x05, PUSH_I8, "push.i8", 0, 1, 2, 0) -OPDEF(0x06, PUSH_I32, "push.i32", 0, 1, 5, 0) -OPDEF(0x07, PUSH_I64, "push.i64", 0, 1, 9, 0) -ODPEF(0x08, PUSH_F32, "push.f32", 0, 1, 5, 0) -OPDEF(0x09, PUSH_F64, "push.f64", 0, 1, 9, 0) -OPDEF(0x0A, PUSH_STR, "push.s", 0, 1, 5, 0) - -// Get/set local variables. -OPDEF(0x10, GETLOCAL, "getlocal", 0, 1, 2, 0) -OPDEF(0x11, GETLOCAL_W, "getlocal.w", 0, 1, 3, 0) -OPDEF(0x12, GETLOCAL_0, "getlocal.0", 0, 1, 1, 0) -OPDEF(0x13, GETLOCAL_1, "getlocal.1", 0, 1, 1, 0) -OPDEF(0x14, GETLOCAL_2, "getlocal.2", 0, 1, 1, 0) -OPDEF(0x15, GETLOCAL_3, "getlocal.3", 0, 1, 1, 0) -OPDEF(0x18, SETLOCAL, "setlocal", 1, 0, 2, 0) -OPDEF(0x19, SETLOCAL_W, "setlocal.w", 1, 0, 3, 0) -OPDEF(0x1A, SETLOCAL_0, "setlocal.0", 1, 0, 1, 0) -OPDEF(0x1B, SETLOCAL_1, "setlocal.1", 1, 0, 1, 0) -OPDEF(0x1C, SETLOCAL_2, "setlocal.2", 1, 0, 1, 0) -OPDEF(0x1D, SETLOCAL_3, "setlocal.3", 1, 0, 1, 0) - -// Local variable references. -OPDEF(0x1E, REFLOCAL, "reflocal", 0, 1, 3, 0) -OPDEF(0x1F, LDREF, "ldref", 1, 1, 1, 0) -OPDEF(0x20, STREF, "stref", 1, 0, 1, 0) - -// Math operators. -OPDEF(0x40, ADD, "add", 2, 1, 1, 0) -OPDEF(0x41, SUB, "sub", 2, 1, 1, 0) -OPDEF(0x42, MUL, "mul", 2, 1, 1, 0) -OPDEF(0x43, DIV, "div", 2, 1, 1, 0) -OPDEF(0x44, MOD, "mod", 2, 1, 1, 0) -OPDEF(0x45, NEG, "neg", 1, 1, 1, 0) -OPDEF(0x46, SHR, "shr", 2, 1, 1, 0) -OPDEF(0x47, USHR, "ushr", 2, 1, 1, 0) -OPDEF(0x48, SHL, "shl", 2, 1, 1, 0) -OPDEF(0x49, BITOR, "bitor", 2, 1, 1, 0) -OPDEF(0x4A, BITAND, "bitand", 2, 1, 1, 0) -OPDEF(0x4B, BITXOR, "bitxor", 2, 1, 1, 0) -OPDEF(0x4C, BITNOT, "bitnot", 1, 1, 1, 0) - -// Logical operators. -OPDEF(0x60, AND, "and", 2, 1, 1, 0) -OPDEF(0x61, OR, "or", 2, 1, 1, 0) -OPDEF(0x62, NOT, "not", 1, 1, 1, 0) -OPDEF(0x63, LT, "lt", 2, 1, 1, 0) -OPDEF(0x64, LE, "le", 2, 1, 1, 0) -OPDEF(0x65, GT, "gt", 2, 1, 1, 0) -OPDEF(0x66, GE, "ge", 2, 1, 1, 0) -OPDEF(0x67, EQ, "eq", 2, 1, 1, 0) -OPDEF(0x68, NE, "ne", 2, 1, 1, 0) - -// Branching operators. -OPDEF(0x70, JUMP, "jump", 0, 0, 1, 0) -OPDEF(0x71, JT, "jt", 1, 0, 1, 0) -OPDEF(0x72, JF, "jf", 1, 0, 1, 0) -OPDEF(0x73, JLT, "jlt", 2, 0, 1, 0) -OPDEF(0x74, JLE, "jle", 2, 0, 1, 0) -OPDEF(0x75, JGT, "jgt", 2, 0, 1, 0) -OPDEF(0x76, JGE, "jge", 2, 0, 1, 0) -OPDEF(0x77, JEQ, "jeq", 2, 0, 1, 0) -OPDEF(0x78, JNE, "jne", 2, 0, 1, 0) - -// Function calling. -// -// The low 4 bits of the index for OP_CALL and OP_CALL_A indicate the type -// of call: -// 0000 - 0x0 : Invoke a method constant such as a native or global function. -// Bits 4-31 are an index into the .methods table. -// -// Call is followed by a method identifier. -OPDEF(0x90, CALL, "call", -1, -1, 5, 0) -// Same as call.a but followed with a variadic argument count. -OPDEF(0x91, CALL_A, "call.a", -1, -1, 9, 0) - -// Array has a typeid and pops a length off the stack. -OPDEF(0x96, ARRAY, "newarray", 1, 1, 5, 0) -// Fixedarray has an offset into the .types table. -OPDEF(0x97, FIXEDARRAY, "fixedarray", 0, 1, 5, 0) - -// Advanced stack operations. -OPDEF(0xB0, DUP, "dup", 1, 2, 1, 0) - - -} // namespace sp - -#endif // _include_spfile_headers_v2_opcodes_h_