mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-23 12:32:09 +00:00
Various fixes to vm_interpreted.c:
- Add opStack protection - Fix dataMask check for OP_BLOCK_COPY - Add instruction number check for conditional jumps - Make errors in VM_PrepareInterpreter nonfatal
This commit is contained in:
parent
af5020c57c
commit
83522282f1
5 changed files with 156 additions and 169 deletions
|
@ -949,3 +949,25 @@ void VM_LogSyscalls( int *args ) {
|
||||||
fprintf(f, "%i: %p (%i) = %i %i %i %i\n", callnum, (void*)(args - (int *)currentVM->dataBase),
|
fprintf(f, "%i: %p (%i) = %i %i %i %i\n", callnum, (void*)(args - (int *)currentVM->dataBase),
|
||||||
args[0], args[1], args[2], args[3], args[4] );
|
args[0], args[1], args[2], args[3], args[4] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
VM_BlockCopy
|
||||||
|
Executes a block copy operation within currentVM data space
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
|
||||||
|
void VM_BlockCopy(unsigned int dest, unsigned int src, size_t n)
|
||||||
|
{
|
||||||
|
unsigned int dataMask = currentVM->dataMask;
|
||||||
|
|
||||||
|
if ((dest & dataMask) != dest
|
||||||
|
|| (src & dataMask) != src
|
||||||
|
|| ((dest + n) & dataMask) != dest + n
|
||||||
|
|| ((src + n) & dataMask) != src + n)
|
||||||
|
{
|
||||||
|
Com_Error(ERR_DROP, "OP_BLOCK_COPY out of range!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_Memcpy(currentVM->dataBase + dest, currentVM->dataBase + src, n);
|
||||||
|
}
|
||||||
|
|
|
@ -192,9 +192,8 @@ void VM_PrepareInterpreter( vm_t *vm, vmHeader_t *header ) {
|
||||||
|
|
||||||
op = (int)code[ byte_pc ];
|
op = (int)code[ byte_pc ];
|
||||||
codeBase[int_pc] = op;
|
codeBase[int_pc] = op;
|
||||||
if ( byte_pc > header->codeLength ) {
|
if(byte_pc > header->codeLength)
|
||||||
Com_Error( ERR_FATAL, "VM_PrepareInterpreter: pc > header->codeLength" );
|
Com_Error(ERR_DROP, "VM_PrepareInterpreter: pc > header->codeLength");
|
||||||
}
|
|
||||||
|
|
||||||
byte_pc++;
|
byte_pc++;
|
||||||
int_pc++;
|
int_pc++;
|
||||||
|
@ -265,6 +264,9 @@ void VM_PrepareInterpreter( vm_t *vm, vmHeader_t *header ) {
|
||||||
case OP_LEF:
|
case OP_LEF:
|
||||||
case OP_GTF:
|
case OP_GTF:
|
||||||
case OP_GEF:
|
case OP_GEF:
|
||||||
|
if(codeBase[int_pc] < 0 || codeBase[int_pc] > vm->instructionCount)
|
||||||
|
Com_Error(ERR_DROP, "VM_PrepareInterpreter: Jump to invalid instruction number");
|
||||||
|
|
||||||
// codeBase[pc] is the instruction index. Convert that into an offset into
|
// codeBase[pc] is the instruction index. Convert that into an offset into
|
||||||
//the int-aligned codeBase[] by the lookup table.
|
//the int-aligned codeBase[] by the lookup table.
|
||||||
codeBase[int_pc] = vm->instructionPointers[codeBase[int_pc]];
|
codeBase[int_pc] = vm->instructionPointers[codeBase[int_pc]];
|
||||||
|
@ -312,11 +314,12 @@ locals from sp
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEBUGSTR va("%s%i", VM_Indent(vm), opStack-stack )
|
#define DEBUGSTR va("%s%i", VM_Indent(vm), opStackOfs)
|
||||||
|
|
||||||
int VM_CallInterpreted( vm_t *vm, int *args ) {
|
int VM_CallInterpreted( vm_t *vm, int *args ) {
|
||||||
int stack[OPSTACK_SIZE];
|
byte stack[OPSTACK_SIZE + 15];
|
||||||
int *opStack;
|
register int *opStack;
|
||||||
|
register uint8_t opStackOfs;
|
||||||
int programCounter;
|
int programCounter;
|
||||||
int programStack;
|
int programStack;
|
||||||
int stackOnEntry;
|
int stackOnEntry;
|
||||||
|
@ -345,10 +348,6 @@ int VM_CallInterpreted( vm_t *vm, int *args ) {
|
||||||
codeImage = (int *)vm->codeBase;
|
codeImage = (int *)vm->codeBase;
|
||||||
dataMask = vm->dataMask;
|
dataMask = vm->dataMask;
|
||||||
|
|
||||||
// leave a free spot at start of stack so
|
|
||||||
// that as long as opStack is valid, opStack-1 will
|
|
||||||
// not corrupt anything
|
|
||||||
opStack = stack;
|
|
||||||
programCounter = 0;
|
programCounter = 0;
|
||||||
|
|
||||||
programStack -= 48;
|
programStack -= 48;
|
||||||
|
@ -368,6 +367,13 @@ int VM_CallInterpreted( vm_t *vm, int *args ) {
|
||||||
|
|
||||||
VM_Debug(0);
|
VM_Debug(0);
|
||||||
|
|
||||||
|
// leave a free spot at start of stack so
|
||||||
|
// that as long as opStack is valid, opStack-1 will
|
||||||
|
// not corrupt anything
|
||||||
|
opStack = PADP(stack, 16);
|
||||||
|
*opStack = 0xDEADBEEF;
|
||||||
|
opStackOfs = 0;
|
||||||
|
|
||||||
// vm_debugLevel=2;
|
// vm_debugLevel=2;
|
||||||
// main interpreter loop, will exit when a LEAVE instruction
|
// main interpreter loop, will exit when a LEAVE instruction
|
||||||
// grabs the -1 program counter
|
// grabs the -1 program counter
|
||||||
|
@ -379,27 +385,23 @@ int VM_CallInterpreted( vm_t *vm, int *args ) {
|
||||||
// unsigned int r2;
|
// unsigned int r2;
|
||||||
|
|
||||||
nextInstruction:
|
nextInstruction:
|
||||||
r0 = ((int *)opStack)[0];
|
r0 = opStack[opStackOfs];
|
||||||
r1 = ((int *)opStack)[-1];
|
r1 = opStack[(uint8_t) (opStackOfs - 1)];
|
||||||
nextInstruction2:
|
nextInstruction2:
|
||||||
#ifdef DEBUG_VM
|
#ifdef DEBUG_VM
|
||||||
if ( (unsigned)programCounter >= vm->codeLength ) {
|
if ( (unsigned)programCounter >= vm->codeLength ) {
|
||||||
Com_Error( ERR_DROP, "VM pc out of range" );
|
Com_Error( ERR_DROP, "VM pc out of range" );
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
if ( opStack < stack ) {
|
|
||||||
Com_Error( ERR_DROP, "VM opStack underflow" );
|
|
||||||
}
|
|
||||||
if ( opStack >= stack+OPSTACK_SIZE ) {
|
|
||||||
Com_Error( ERR_DROP, "VM opStack overflow" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( programStack <= vm->stackBottom ) {
|
if ( programStack <= vm->stackBottom ) {
|
||||||
Com_Error( ERR_DROP, "VM stack overflow" );
|
Com_Error( ERR_DROP, "VM stack overflow" );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( programStack & 3 ) {
|
if ( programStack & 3 ) {
|
||||||
Com_Error( ERR_DROP, "VM program stack misaligned" );
|
Com_Error( ERR_DROP, "VM program stack misaligned" );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( vm_debugLevel > 1 ) {
|
if ( vm_debugLevel > 1 ) {
|
||||||
|
@ -413,79 +415,67 @@ nextInstruction2:
|
||||||
#ifdef DEBUG_VM
|
#ifdef DEBUG_VM
|
||||||
default:
|
default:
|
||||||
Com_Error( ERR_DROP, "Bad VM instruction" ); // this should be scanned on load!
|
Com_Error( ERR_DROP, "Bad VM instruction" ); // this should be scanned on load!
|
||||||
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
case OP_BREAK:
|
case OP_BREAK:
|
||||||
vm->breakCount++;
|
vm->breakCount++;
|
||||||
goto nextInstruction2;
|
goto nextInstruction2;
|
||||||
case OP_CONST:
|
case OP_CONST:
|
||||||
opStack++;
|
opStackOfs++;
|
||||||
r1 = r0;
|
r1 = r0;
|
||||||
r0 = *opStack = r2;
|
r0 = opStack[opStackOfs] = r2;
|
||||||
|
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
goto nextInstruction2;
|
goto nextInstruction2;
|
||||||
case OP_LOCAL:
|
case OP_LOCAL:
|
||||||
opStack++;
|
opStackOfs++;
|
||||||
r1 = r0;
|
r1 = r0;
|
||||||
r0 = *opStack = r2+programStack;
|
r0 = opStack[opStackOfs] = r2+programStack;
|
||||||
|
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
goto nextInstruction2;
|
goto nextInstruction2;
|
||||||
|
|
||||||
case OP_LOAD4:
|
case OP_LOAD4:
|
||||||
#ifdef DEBUG_VM
|
#ifdef DEBUG_VM
|
||||||
if ( *opStack & 3 ) {
|
if(opStack[opStackOfs] & 3)
|
||||||
|
{
|
||||||
Com_Error( ERR_DROP, "OP_LOAD4 misaligned" );
|
Com_Error( ERR_DROP, "OP_LOAD4 misaligned" );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
r0 = *opStack = *(int *)&image[ r0&dataMask&~3 ];
|
r0 = opStack[opStackOfs] = *(int *) &image[r0 & dataMask & ~3 ];
|
||||||
goto nextInstruction2;
|
goto nextInstruction2;
|
||||||
case OP_LOAD2:
|
case OP_LOAD2:
|
||||||
r0 = *opStack = *(unsigned short *)&image[ r0&dataMask&~1 ];
|
r0 = opStack[opStackOfs] = *(unsigned short *)&image[ r0&dataMask&~1 ];
|
||||||
goto nextInstruction2;
|
goto nextInstruction2;
|
||||||
case OP_LOAD1:
|
case OP_LOAD1:
|
||||||
r0 = *opStack = image[ r0&dataMask ];
|
r0 = opStack[opStackOfs] = image[ r0&dataMask ];
|
||||||
goto nextInstruction2;
|
goto nextInstruction2;
|
||||||
|
|
||||||
case OP_STORE4:
|
case OP_STORE4:
|
||||||
*(int *)&image[ r1&(dataMask & ~3) ] = r0;
|
*(int *)&image[ r1&(dataMask & ~3) ] = r0;
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_STORE2:
|
case OP_STORE2:
|
||||||
*(short *)&image[ r1&(dataMask & ~1) ] = r0;
|
*(short *)&image[ r1&(dataMask & ~1) ] = r0;
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_STORE1:
|
case OP_STORE1:
|
||||||
image[ r1&dataMask ] = r0;
|
image[ r1&dataMask ] = r0;
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_ARG:
|
case OP_ARG:
|
||||||
// single byte offset from programStack
|
// single byte offset from programStack
|
||||||
*(int *)&image[ (codeImage[programCounter] + programStack)&dataMask&~3 ] = r0;
|
*(int *)&image[ (codeImage[programCounter] + programStack)&dataMask&~3 ] = r0;
|
||||||
opStack--;
|
opStackOfs--;
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_BLOCK_COPY:
|
case OP_BLOCK_COPY:
|
||||||
{
|
VM_BlockCopy(r1, r0, r2);
|
||||||
int *src, *dest;
|
|
||||||
int count, srci, desti;
|
|
||||||
|
|
||||||
count = r2;
|
|
||||||
// MrE: copy range check
|
|
||||||
srci = r0 & dataMask;
|
|
||||||
desti = r1 & dataMask;
|
|
||||||
count = ((srci + count) & dataMask) - srci;
|
|
||||||
count = ((desti + count) & dataMask) - desti;
|
|
||||||
|
|
||||||
src = (int *)&image[ srci ];
|
|
||||||
dest = (int *)&image[ desti ];
|
|
||||||
|
|
||||||
memcpy(dest, src, count);
|
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
}
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
|
@ -494,7 +484,7 @@ nextInstruction2:
|
||||||
|
|
||||||
// jump to the location on the stack
|
// jump to the location on the stack
|
||||||
programCounter = r0;
|
programCounter = r0;
|
||||||
opStack--;
|
opStackOfs--;
|
||||||
if ( programCounter < 0 ) {
|
if ( programCounter < 0 ) {
|
||||||
// system call
|
// system call
|
||||||
int r;
|
int r;
|
||||||
|
@ -539,8 +529,8 @@ nextInstruction2:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// save return value
|
// save return value
|
||||||
opStack++;
|
opStackOfs++;
|
||||||
*opStack = r;
|
opStack[opStackOfs] = r;
|
||||||
programCounter = *(int *)&image[ programStack ];
|
programCounter = *(int *)&image[ programStack ];
|
||||||
// vm->callLevel = temp;
|
// vm->callLevel = temp;
|
||||||
#ifdef DEBUG_VM
|
#ifdef DEBUG_VM
|
||||||
|
@ -550,6 +540,7 @@ nextInstruction2:
|
||||||
#endif
|
#endif
|
||||||
} else if ( (unsigned)programCounter >= vm->instructionCount ) {
|
} else if ( (unsigned)programCounter >= vm->instructionCount ) {
|
||||||
Com_Error( ERR_DROP, "VM program counter out of range in OP_CALL" );
|
Com_Error( ERR_DROP, "VM program counter out of range in OP_CALL" );
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
programCounter = vm->instructionPointers[ programCounter ];
|
programCounter = vm->instructionPointers[ programCounter ];
|
||||||
}
|
}
|
||||||
|
@ -557,10 +548,10 @@ nextInstruction2:
|
||||||
|
|
||||||
// push and pop are only needed for discarded or bad function return values
|
// push and pop are only needed for discarded or bad function return values
|
||||||
case OP_PUSH:
|
case OP_PUSH:
|
||||||
opStack++;
|
opStackOfs++;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_POP:
|
case OP_POP:
|
||||||
opStack--;
|
opStackOfs--;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_ENTER:
|
case OP_ENTER:
|
||||||
|
@ -607,6 +598,7 @@ nextInstruction2:
|
||||||
goto done;
|
goto done;
|
||||||
} else if ( (unsigned)programCounter >= vm->codeLength ) {
|
} else if ( (unsigned)programCounter >= vm->codeLength ) {
|
||||||
Com_Error( ERR_DROP, "VM program counter out of range in OP_LEAVE" );
|
Com_Error( ERR_DROP, "VM program counter out of range in OP_LEAVE" );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
|
@ -618,15 +610,18 @@ nextInstruction2:
|
||||||
|
|
||||||
case OP_JUMP:
|
case OP_JUMP:
|
||||||
if ( (unsigned)r0 >= vm->instructionCount )
|
if ( (unsigned)r0 >= vm->instructionCount )
|
||||||
|
{
|
||||||
Com_Error( ERR_DROP, "VM program counter out of range in OP_JUMP" );
|
Com_Error( ERR_DROP, "VM program counter out of range in OP_JUMP" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
programCounter = vm->instructionPointers[ r0 ];
|
programCounter = vm->instructionPointers[ r0 ];
|
||||||
|
|
||||||
opStack--;
|
opStackOfs--;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_EQ:
|
case OP_EQ:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( r1 == r0 ) {
|
if ( r1 == r0 ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -636,7 +631,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_NE:
|
case OP_NE:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( r1 != r0 ) {
|
if ( r1 != r0 ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -646,7 +641,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_LTI:
|
case OP_LTI:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( r1 < r0 ) {
|
if ( r1 < r0 ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -656,7 +651,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_LEI:
|
case OP_LEI:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( r1 <= r0 ) {
|
if ( r1 <= r0 ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -666,7 +661,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_GTI:
|
case OP_GTI:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( r1 > r0 ) {
|
if ( r1 > r0 ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -676,7 +671,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_GEI:
|
case OP_GEI:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( r1 >= r0 ) {
|
if ( r1 >= r0 ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -686,7 +681,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_LTU:
|
case OP_LTU:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( ((unsigned)r1) < ((unsigned)r0) ) {
|
if ( ((unsigned)r1) < ((unsigned)r0) ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -696,7 +691,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_LEU:
|
case OP_LEU:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( ((unsigned)r1) <= ((unsigned)r0) ) {
|
if ( ((unsigned)r1) <= ((unsigned)r0) ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -706,7 +701,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_GTU:
|
case OP_GTU:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( ((unsigned)r1) > ((unsigned)r0) ) {
|
if ( ((unsigned)r1) > ((unsigned)r0) ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -716,7 +711,7 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_GEU:
|
case OP_GEU:
|
||||||
opStack -= 2;
|
opStackOfs -= 2;
|
||||||
if ( ((unsigned)r1) >= ((unsigned)r0) ) {
|
if ( ((unsigned)r1) >= ((unsigned)r0) ) {
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
@ -726,68 +721,74 @@ nextInstruction2:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_EQF:
|
case OP_EQF:
|
||||||
if ( ((float *)opStack)[-1] == *(float *)opStack ) {
|
opStackOfs -= 2;
|
||||||
|
|
||||||
|
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] == ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
|
||||||
|
{
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
} else {
|
} else {
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_NEF:
|
case OP_NEF:
|
||||||
if ( ((float *)opStack)[-1] != *(float *)opStack ) {
|
opStackOfs -= 2;
|
||||||
|
|
||||||
|
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] != ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
|
||||||
|
{
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
} else {
|
} else {
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_LTF:
|
case OP_LTF:
|
||||||
if ( ((float *)opStack)[-1] < *(float *)opStack ) {
|
opStackOfs -= 2;
|
||||||
|
|
||||||
|
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] < ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
|
||||||
|
{
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
} else {
|
} else {
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_LEF:
|
case OP_LEF:
|
||||||
if ( ((float *)opStack)[-1] <= *(float *)opStack ) {
|
opStackOfs -= 2;
|
||||||
|
|
||||||
|
if(((float *) opStack)[(uint8_t) ((uint8_t) (opStackOfs + 1))] <= ((float *) opStack)[(uint8_t) ((uint8_t) (opStackOfs + 2))])
|
||||||
|
{
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
} else {
|
} else {
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_GTF:
|
case OP_GTF:
|
||||||
if ( ((float *)opStack)[-1] > *(float *)opStack ) {
|
opStackOfs -= 2;
|
||||||
|
|
||||||
|
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] > ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
|
||||||
|
{
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
} else {
|
} else {
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_GEF:
|
case OP_GEF:
|
||||||
if ( ((float *)opStack)[-1] >= *(float *)opStack ) {
|
opStackOfs -= 2;
|
||||||
|
|
||||||
|
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] >= ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
|
||||||
|
{
|
||||||
programCounter = r2; //vm->instructionPointers[r2];
|
programCounter = r2; //vm->instructionPointers[r2];
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
} else {
|
} else {
|
||||||
programCounter += 1;
|
programCounter += 1;
|
||||||
opStack -= 2;
|
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,101 +796,101 @@ nextInstruction2:
|
||||||
//===================================================================
|
//===================================================================
|
||||||
|
|
||||||
case OP_NEGI:
|
case OP_NEGI:
|
||||||
*opStack = -r0;
|
opStack[opStackOfs] = -r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
opStack[-1] = r1 + r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = r1 + r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_SUB:
|
case OP_SUB:
|
||||||
opStack[-1] = r1 - r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = r1 - r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_DIVI:
|
case OP_DIVI:
|
||||||
opStack[-1] = r1 / r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = r1 / r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_DIVU:
|
case OP_DIVU:
|
||||||
opStack[-1] = ((unsigned)r1) / ((unsigned)r0);
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = ((unsigned) r1) / ((unsigned) r0);
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_MODI:
|
case OP_MODI:
|
||||||
opStack[-1] = r1 % r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = r1 % r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_MODU:
|
case OP_MODU:
|
||||||
opStack[-1] = ((unsigned)r1) % (unsigned)r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = ((unsigned) r1) % ((unsigned) r0);
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_MULI:
|
case OP_MULI:
|
||||||
opStack[-1] = r1 * r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = r1 * r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_MULU:
|
case OP_MULU:
|
||||||
opStack[-1] = ((unsigned)r1) * ((unsigned)r0);
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = ((unsigned) r1) * ((unsigned) r0);
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_BAND:
|
case OP_BAND:
|
||||||
opStack[-1] = ((unsigned)r1) & ((unsigned)r0);
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = ((unsigned) r1) & ((unsigned) r0);
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_BOR:
|
case OP_BOR:
|
||||||
opStack[-1] = ((unsigned)r1) | ((unsigned)r0);
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = ((unsigned) r1) | ((unsigned) r0);
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_BXOR:
|
case OP_BXOR:
|
||||||
opStack[-1] = ((unsigned)r1) ^ ((unsigned)r0);
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = ((unsigned) r1) ^ ((unsigned) r0);
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_BCOM:
|
case OP_BCOM:
|
||||||
*opStack = ~ ((unsigned)r0);
|
opStack[opStackOfs] = ~((unsigned) r0);
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_LSH:
|
case OP_LSH:
|
||||||
opStack[-1] = r1 << r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = r1 << r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_RSHI:
|
case OP_RSHI:
|
||||||
opStack[-1] = r1 >> r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = r1 >> r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_RSHU:
|
case OP_RSHU:
|
||||||
opStack[-1] = ((unsigned)r1) >> r0;
|
opStackOfs--;
|
||||||
opStack--;
|
opStack[opStackOfs] = ((unsigned) r1) >> r0;
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_NEGF:
|
case OP_NEGF:
|
||||||
*(float *)opStack = -*(float *)opStack;
|
((float *) opStack)[opStackOfs] = -((float *) opStack)[opStackOfs];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_ADDF:
|
case OP_ADDF:
|
||||||
*(float *)(opStack-1) = *(float *)(opStack-1) + *(float *)opStack;
|
opStackOfs--;
|
||||||
opStack--;
|
((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] + ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_SUBF:
|
case OP_SUBF:
|
||||||
*(float *)(opStack-1) = *(float *)(opStack-1) - *(float *)opStack;
|
opStackOfs--;
|
||||||
opStack--;
|
((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] - ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_DIVF:
|
case OP_DIVF:
|
||||||
*(float *)(opStack-1) = *(float *)(opStack-1) / *(float *)opStack;
|
opStackOfs--;
|
||||||
opStack--;
|
((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] / ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_MULF:
|
case OP_MULF:
|
||||||
*(float *)(opStack-1) = *(float *)(opStack-1) * *(float *)opStack;
|
opStackOfs--;
|
||||||
opStack--;
|
((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] * ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
|
|
||||||
case OP_CVIF:
|
case OP_CVIF:
|
||||||
*(float *)opStack = (float)*opStack;
|
((float *) opStack)[opStackOfs] = (float) opStack[opStackOfs];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_CVFI:
|
case OP_CVFI:
|
||||||
*opStack = (int) *(float *)opStack;
|
opStack[opStackOfs] = (int) ((float *) opStack)[opStackOfs];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_SEX8:
|
case OP_SEX8:
|
||||||
*opStack = (signed char)*opStack;
|
opStack[opStackOfs] = (signed char) opStack[opStackOfs];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
case OP_SEX16:
|
case OP_SEX16:
|
||||||
*opStack = (short)*opStack;
|
opStack[opStackOfs] = (short) opStack[opStackOfs];
|
||||||
goto nextInstruction;
|
goto nextInstruction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -897,12 +898,11 @@ nextInstruction2:
|
||||||
done:
|
done:
|
||||||
vm->currentlyInterpreting = qfalse;
|
vm->currentlyInterpreting = qfalse;
|
||||||
|
|
||||||
if ( opStack != &stack[1] ) {
|
if (opStackOfs != 1 || *opStack != 0xDEADBEEF)
|
||||||
Com_Error( ERR_DROP, "Interpreter error: opStack = %ld", (long int) (opStack - stack) );
|
Com_Error(ERR_DROP, "Interpreter error: opStack[0] = %X, opStackOfs = %d", opStack[0], opStackOfs);
|
||||||
}
|
|
||||||
|
|
||||||
vm->programStack = stackOnEntry;
|
vm->programStack = stackOnEntry;
|
||||||
|
|
||||||
// return the result
|
// return the result
|
||||||
return *opStack;
|
return opStack[opStackOfs];
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,3 +190,5 @@ vmSymbol_t *VM_ValueToFunctionSymbol( vm_t *vm, int value );
|
||||||
int VM_SymbolToValue( vm_t *vm, const char *symbol );
|
int VM_SymbolToValue( vm_t *vm, const char *symbol );
|
||||||
const char *VM_ValueToSymbol( vm_t *vm, int value );
|
const char *VM_ValueToSymbol( vm_t *vm, int value );
|
||||||
void VM_LogSyscalls( int *args );
|
void VM_LogSyscalls( int *args );
|
||||||
|
|
||||||
|
void VM_BlockCopy(unsigned int dest, unsigned int src, size_t n);
|
||||||
|
|
|
@ -386,28 +386,6 @@ static void ErrJump(void)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
DoBlockCopy
|
|
||||||
Executes OP_BLOCK_COPY
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
|
|
||||||
void DoBlockCopy(unsigned int dest, unsigned int src, size_t n)
|
|
||||||
{
|
|
||||||
unsigned int dataMask = currentVM->dataMask;
|
|
||||||
|
|
||||||
if ((dest & dataMask) != dest
|
|
||||||
|| (src & dataMask) != src
|
|
||||||
|| ((dest + n) & dataMask) != dest + n
|
|
||||||
|| ((src + n) & dataMask) != src + n)
|
|
||||||
{
|
|
||||||
Com_Error(ERR_DROP, "OP_BLOCK_COPY out of range!");
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(currentVM->dataBase + dest, currentVM->dataBase + src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
DoSyscall
|
DoSyscall
|
||||||
|
@ -493,7 +471,7 @@ static void DoSyscall(void)
|
||||||
if(opStackOfs < 1)
|
if(opStackOfs < 1)
|
||||||
Com_Error(ERR_DROP, "VM_BLOCK_COPY failed due to corrupted opStack");
|
Com_Error(ERR_DROP, "VM_BLOCK_COPY failed due to corrupted opStack");
|
||||||
|
|
||||||
DoBlockCopy(opStackBase[opStackOfs - 1], opStackBase[opStackOfs], arg);
|
VM_BlockCopy(opStackBase[(opStackOfs - 1)], opStackBase[opStackOfs], arg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Com_Error(ERR_DROP, "Unknown VM operation %d", syscallNum);
|
Com_Error(ERR_DROP, "Unknown VM operation %d", syscallNum);
|
||||||
|
|
|
@ -381,21 +381,6 @@ static void* getentrypoint(vm_t* vm)
|
||||||
return vm->codeBase;
|
return vm->codeBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CROSSCALL block_copy_vm(unsigned dest, unsigned src, unsigned count)
|
|
||||||
{
|
|
||||||
unsigned dataMask = currentVM->dataMask;
|
|
||||||
|
|
||||||
if ((dest & dataMask) != dest
|
|
||||||
|| (src & dataMask) != src
|
|
||||||
|| ((dest+count) & dataMask) != dest + count
|
|
||||||
|| ((src+count) & dataMask) != src + count)
|
|
||||||
{
|
|
||||||
Com_Error(ERR_DROP, "OP_BLOCK_COPY out of range!");
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CROSSCALL eop(void)
|
static void CROSSCALL eop(void)
|
||||||
{
|
{
|
||||||
Com_Error(ERR_DROP, "End of program reached without return!");
|
Com_Error(ERR_DROP, "End of program reached without return!");
|
||||||
|
@ -782,7 +767,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
|
||||||
emit("movl 4(%%r9, %%rbx, 4), %%edi"); // 1st argument dest
|
emit("movl 4(%%r9, %%rbx, 4), %%edi"); // 1st argument dest
|
||||||
emit("movl 8(%%r9, %%rbx, 4), %%rsi"); // 2nd argument src
|
emit("movl 8(%%r9, %%rbx, 4), %%rsi"); // 2nd argument src
|
||||||
emit("movl $%d, %%edx", iarg); // 3rd argument count
|
emit("movl $%d, %%edx", iarg); // 3rd argument count
|
||||||
emit("movq $%"PRIu64", %%rax", (intptr_t) block_copy_vm);
|
emit("movq $%"PRIu64", %%rax", (intptr_t) VM_BlockCopy);
|
||||||
emit("callq *%%rax");
|
emit("callq *%%rax");
|
||||||
emit("pop %%rsi");
|
emit("pop %%rsi");
|
||||||
emit("addq %%rsi, %%rsp");
|
emit("addq %%rsi, %%rsp");
|
||||||
|
|
Loading…
Reference in a new issue