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