1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Quake III Arena source code; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 #include "q_shared.h" 23 #include "qcommon.h" 24 25 // Max number of arguments to pass from engine to vm's vmMain function. 26 // command number + 12 arguments 27 #define MAX_VMMAIN_ARGS 13 28 29 // Max number of arguments to pass from a vm to engine's syscall handler function for the vm. 30 // syscall number + 15 arguments 31 #define MAX_VMSYSCALL_ARGS 16 32 33 // don't change, this is hardcoded into x86 VMs, opStack protection relies 34 // on this 35 #define OPSTACK_SIZE 1024 36 #define OPSTACK_MASK (OPSTACK_SIZE-1) 37 38 // don't change 39 // Hardcoded in q3asm a reserved at end of bss 40 #define PROGRAM_STACK_SIZE 0x10000 41 #define PROGRAM_STACK_MASK (PROGRAM_STACK_SIZE-1) 42 43 typedef enum { 44 OP_UNDEF, 45 46 OP_IGNORE, 47 48 OP_BREAK, 49 50 OP_ENTER, 51 OP_LEAVE, 52 OP_CALL, 53 OP_PUSH, 54 OP_POP, 55 56 OP_CONST, 57 OP_LOCAL, 58 59 OP_JUMP, 60 61 //------------------- 62 63 OP_EQ, 64 OP_NE, 65 66 OP_LTI, 67 OP_LEI, 68 OP_GTI, 69 OP_GEI, 70 71 OP_LTU, 72 OP_LEU, 73 OP_GTU, 74 OP_GEU, 75 76 OP_EQF, 77 OP_NEF, 78 79 OP_LTF, 80 OP_LEF, 81 OP_GTF, 82 OP_GEF, 83 84 //------------------- 85 86 OP_LOAD1, 87 OP_LOAD2, 88 OP_LOAD4, 89 OP_STORE1, 90 OP_STORE2, 91 OP_STORE4, // *(stack[top-1]) = stack[top] 92 OP_ARG, 93 94 OP_BLOCK_COPY, 95 96 //------------------- 97 98 OP_SEX8, 99 OP_SEX16, 100 101 OP_NEGI, 102 OP_ADD, 103 OP_SUB, 104 OP_DIVI, 105 OP_DIVU, 106 OP_MODI, 107 OP_MODU, 108 OP_MULI, 109 OP_MULU, 110 111 OP_BAND, 112 OP_BOR, 113 OP_BXOR, 114 OP_BCOM, 115 116 OP_LSH, 117 OP_RSHI, 118 OP_RSHU, 119 120 OP_NEGF, 121 OP_ADDF, 122 OP_SUBF, 123 OP_DIVF, 124 OP_MULF, 125 126 OP_CVIF, 127 OP_CVFI 128 } opcode_t; 129 130 131 132 typedef int vmptr_t; 133 134 typedef struct vmSymbol_s { 135 struct vmSymbol_s *next; 136 int symValue; 137 int profileCount; 138 char symName[1]; // variable sized 139 } vmSymbol_t; 140 141 #define VM_OFFSET_PROGRAM_STACK 0 142 #define VM_OFFSET_SYSTEM_CALL 4 143 144 struct vm_s { 145 // DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES 146 // USED BY THE ASM CODE 147 int programStack; // the vm may be recursively entered 148 intptr_t (*systemCall)( intptr_t *parms ); 149 150 //------------------------------------ 151 152 char name[MAX_QPATH]; 153 void *searchPath; // hint for FS_ReadFileDir() 154 155 // for dynamic linked modules 156 void *dllHandle; 157 intptr_t (QDECL *entryPoint)( intptr_t callNum, ... ); 158 void (*destroy)(vm_t* self); 159 160 // for interpreted modules 161 qboolean currentlyInterpreting; 162 163 qboolean compiled; 164 byte *codeBase; 165 int entryOfs; 166 int codeLength; 167 168 intptr_t *instructionPointers; 169 int instructionCount; 170 171 byte *dataBase; 172 int dataMask; 173 int dataAlloc; // actually allocated 174 175 int heapLength; // length of QVMs data 176 int heapAlloc; // QVM's current allocate point 177 int heapAllocTop; // QVM's current temporary memory allocate point 178 179 int stackBottom; // if programStack < stackBottom, error 180 181 int numSymbols; 182 struct vmSymbol_s *symbols; 183 184 int callLevel; // counts recursive VM_Call 185 int breakFunction; // increment breakCount on function entry to this 186 int breakCount; 187 188 byte *jumpTableTargets; 189 int numJumpTableTargets; 190 }; 191 192 193 extern vm_t *currentVM; 194 extern int vm_debugLevel; 195 196 void VM_Compile( vm_t *vm, vmHeader_t *header ); 197 int VM_CallCompiled( vm_t *vm, int *args ); 198 199 void VM_PrepareInterpreter( vm_t *vm, vmHeader_t *header ); 200 int VM_CallInterpreted( vm_t *vm, int *args ); 201 202 vmSymbol_t *VM_ValueToFunctionSymbol( vm_t *vm, int value ); 203 int VM_SymbolToValue( vm_t *vm, const char *symbol ); 204 const char *VM_ValueToSymbol( vm_t *vm, int value ); 205 void VM_LogSyscalls( int *args ); 206 207 void VM_BlockCopy(unsigned int dest, unsigned int src, size_t n); 208