cnq3/code/qcommon/vm_local.h
myT f327428475 full x64 support with a VM based on quake3e OCT 21 2016
the VM compiler uses SSE for floating-point ops when possible
2017-01-11 14:24:58 +01:00

259 lines
4.7 KiB
C

/*
===========================================================================
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"
#define MAX_OPSTACK_SIZE 512
#define PROC_OPSTACK_SIZE 30
#define VMMAIN_CALL_ARGS 13
// hardcoded in q3asm and reserved at end of bss
#define PROGRAM_STACK_SIZE 0x10000
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,
OP_MAX
} opcode_t;
// macro opcode sequences
typedef enum {
MOP_UNDEF = OP_MAX,
MOP_IGNORE4,
MOP_ADD4,
MOP_SUB4,
MOP_BAND4,
MOP_BOR4,
MOP_CALCF4,
} macro_op_t;
typedef struct {
int value;
byte op;
byte opStack;
byte jused; // boolean
byte swtch; // boolean
} instruction_t;
extern const char *opname[OP_MAX];
typedef int vmptr_t;
typedef struct vmSymbol_s {
struct vmSymbol_s *next;
int symValue;
int profileCount;
char symName[1]; // variable sized
} vmSymbol_t;
typedef union vmFunc_u {
byte *ptr;
void (*func)(void);
} vmFunc_t;
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
syscall_t systemCall;
byte *dataBase;
int *opStack; // pointer to local function stack
int instructionCount;
intptr_t *instructionPointers;
//------------------------------------
const char *name;
// for dynamic linked modules
void *dllHandle;
dllSyscall_t entryPoint;
void (*destroy)(vm_t* self);
// for interpreted modules
qboolean currentlyInterpreting;
qboolean compiled;
vmFunc_t codeBase;
int codeLength;
int dataMask;
int dataLength; // exact data segment length
int stackBottom; // if programStack < stackBottom, error
int *opStackTop;
int numSymbols;
vmSymbol_t *symbols;
int callLevel; // counts recursive VM_Call
int breakFunction; // increment breakCount on function entry to this
int breakCount;
byte *jumpTableTargets;
int numJumpTableTargets;
uint32_t crc32sum;
vmIndex_t index;
};
extern vm_t *currentVM;
#define VM_MAGIC 0x12721444
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
} vmHeader_t;
qboolean VM_Compile( vm_t *vm, vmHeader_t *header );
int VM_CallCompiled( vm_t *vm, int *args );
qboolean VM_PrepareInterpreter2( vm_t *vm, vmHeader_t *header );
int VM_CallInterpreted2( vm_t *vm, int *args );
const char *VM_LoadInstructions( const vmHeader_t *header, instruction_t *buf );
const char *VM_CheckInstructions( instruction_t *buf, int instructionCount,
const byte *jumpTableTargets,
int numJumpTableTargets,
int dataLength );
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])
#define VM_OF_JUMP (1<<0)
typedef struct opcode_info_s
{
int size;
int stack;
int nargs;
int flags;
} opcode_info_t ;
extern opcode_info_t ops[ OP_MAX ];