/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. This file is part of Quake III Arena source code. Quake III Arena source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "q_shared.h" #include "qcommon.h" typedef enum { OP_UNDEF, OP_IGNORE, OP_BREAK, OP_ENTER, OP_LEAVE, OP_CALL, OP_PUSH, OP_POP, OP_CONST, OP_LOCAL, OP_JUMP, //------------------- OP_EQ, OP_NE, OP_LTI, OP_LEI, OP_GTI, OP_GEI, OP_LTU, OP_LEU, OP_GTU, OP_GEU, OP_EQF, OP_NEF, OP_LTF, OP_LEF, OP_GTF, OP_GEF, //------------------- OP_LOAD1, OP_LOAD2, OP_LOAD4, OP_STORE1, OP_STORE2, OP_STORE4, // *(stack[top-1]) = stack[top] OP_ARG, OP_BLOCK_COPY, //------------------- OP_SEX8, OP_SEX16, OP_NEGI, OP_ADD, OP_SUB, OP_DIVI, OP_DIVU, OP_MODI, OP_MODU, OP_MULI, OP_MULU, OP_BAND, OP_BOR, OP_BXOR, OP_BCOM, OP_LSH, OP_RSHI, OP_RSHU, OP_NEGF, OP_ADDF, OP_SUBF, OP_DIVF, OP_MULF, OP_CVIF, OP_CVFI } opcode_t; typedef struct vmSymbol_s { struct vmSymbol_s *next; int symValue; int profileCount; char symName[1]; // variable sized } vmSymbol_t; #define VM_OFFSET_PROGRAM_STACK 0 #define VM_OFFSET_SYSTEM_CALL 4 struct vm_s { // DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES // USED BY THE ASM CODE int programStack; // the vm may be recursively entered intptr_t (*systemCall)( intptr_t *parms ); //------------------------------------ char name[MAX_QPATH]; // for dynamic linked modules void *dllHandle; intptr_t (QDECL *entryPoint)( int callNum, ... ); void (*destroy)(vm_t* self); qbool compiled; byte *codeBase; int codeLength; int *instructionPointers; int instructionPointersLength; byte *dataBase; int dataMask; int numSymbols; vmSymbol_t *symbols; int stackBottom; // if programStack < stackBottom, error #if defined(NO_VM_COMPILED) int callLevel; // for debug indenting int breakFunction; // increment breakCount on function entry to this int breakCount; #endif byte *jumpTableTargets; int numJumpTableTargets; }; #define VM_MAGIC 0x12721444 #define VM_MAGIC_VER2 0x12721445 typedef struct { int vmMagic; int instructionCount; int codeOffset; int codeLength; int dataOffset; int dataLength; int litLength; // ( dataLength - litLength ) should be byteswapped on load int bssLength; // zero filled memory appended to datalength //!!! below here is VM_MAGIC_VER2 !!! int jtrgLength; // number of jump table targets } vmHeader_t; extern vm_t *currentVM; extern int vm_debugLevel; void VM_Compile( vm_t* vm, const vmHeader_t* header ); int VM_CallCompiled( vm_t* vm, int* args ); #if defined(NO_VM_COMPILED) void VM_PrepareInterpreter( vm_t* vm, const vmHeader_t* header ); int VM_CallInterpreted( vm_t *vm, int *args ); #endif const char* VM_ValueToSymbol( const vm_t* vm, int value ); const vmSymbol_t* VM_ValueToFunctionSymbol( const vm_t* vm, int value ); void VM_LogSyscalls( int *args ); intptr_t VM_ArgPtr( intptr_t intValue ); intptr_t VM_ExplicitArgPtr( const vm_t* vm, intptr_t intValue ); static ID_INLINE float _vmf(intptr_t x) { union { intptr_t l; float f; } t; t.l = x; return t.f; } #define VMF(x) _vmf(args[x])