summaryrefslogtreecommitdiff
path: root/src/qcommon
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2007-07-15 14:15:41 +0000
committerTim Angus <tim@ngus.net>2007-07-15 14:15:41 +0000
commitffbf946dd63dccf0d6b6553c8bc1c9da4d3c89b3 (patch)
tree62b48381afabceca4c2aad7c39e0eeb51e328126 /src/qcommon
parent655d4c12eea45edf2041300eccace352a503b690 (diff)
* Merge of ioq3-r1112
Diffstat (limited to 'src/qcommon')
-rw-r--r--src/qcommon/vm_interpreted.c8
-rw-r--r--src/qcommon/vm_ppc.c1448
-rw-r--r--src/qcommon/vm_ppc_new.c2072
-rw-r--r--src/qcommon/vm_x86_64.c96
4 files changed, 1083 insertions, 2541 deletions
diff --git a/src/qcommon/vm_interpreted.c b/src/qcommon/vm_interpreted.c
index 00aa4710..35096e5b 100644
--- a/src/qcommon/vm_interpreted.c
+++ b/src/qcommon/vm_interpreted.c
@@ -395,9 +395,8 @@ nextInstruction:
r0 = ((int *)opStack)[0];
r1 = ((int *)opStack)[-1];
nextInstruction2:
- opcode = codeImage[ programCounter++ ];
#ifdef DEBUG_VM
- if ( (unsigned)programCounter > vm->codeLength ) {
+ if ( (unsigned)programCounter >= vm->codeLength ) {
Com_Error( ERR_DROP, "VM pc out of range" );
}
@@ -421,6 +420,7 @@ nextInstruction2:
}
profileSymbol->profileCount++;
#endif
+ opcode = codeImage[ programCounter++ ];
switch ( opcode ) {
#ifdef DEBUG_VM
@@ -565,6 +565,8 @@ nextInstruction2:
Com_Printf( "%s<--- %s\n", DEBUGSTR, VM_ValueToSymbol( vm, programCounter ) );
}
#endif
+ } else if ( (unsigned)programCounter >= vm->codeLength ) {
+ Com_Error( ERR_DROP, "VM program counter out of range in OP_CALL" );
} else {
programCounter = vm->instructionPointers[ programCounter ];
}
@@ -620,6 +622,8 @@ nextInstruction2:
// check for leaving the VM
if ( programCounter == -1 ) {
goto done;
+ } else if ( (unsigned)programCounter >= vm->codeLength ) {
+ Com_Error( ERR_DROP, "VM program counter out of range in OP_LEAVE" );
}
goto nextInstruction;
diff --git a/src/qcommon/vm_ppc.c b/src/qcommon/vm_ppc.c
index 9475a833..79fc506f 100644
--- a/src/qcommon/vm_ppc.c
+++ b/src/qcommon/vm_ppc.c
@@ -25,8 +25,101 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "vm_local.h"
-#pragma opt_pointer_analysis off
+#ifdef MACOS_X
+#include <CoreServices/CoreServices.h>
+#endif
+
+#define DEBUG_VM 0
+
+#if DEBUG_VM
+static char *opnames[256] = {
+ "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",
+ "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"
+};
+#endif
typedef enum {
R_REAL_STACK = 1,
@@ -64,6 +157,42 @@ typedef enum {
#define RG_SECOND r13
#define RG_EA r14
+// The deepest value I saw in the Quake3 games was 9.
+#define OP_STACK_MAX_DEPTH 16
+
+// These are all volatile and thus must be saved upon entry to the VM code.
+// NOTE: These are General Purpose Registers (GPR) numbers like the
+// R_ definitions in the regNums_t enum above (31 is the max)
+static int opStackIntRegisters[OP_STACK_MAX_DEPTH] =
+{
+ 16, 17, 18, 19,
+ 20, 21, 22, 23,
+ 24, 25, 26, 27,
+ 28, 29, 30, 31
+};
+
+static unsigned int *opStackLoadInstructionAddr[OP_STACK_MAX_DEPTH];
+
+// We use different registers for the floating point
+// operand stack (these are volatile in the PPC ABI)
+// NOTE: these are Floating Point Register (FPR) numbers, not
+// General Purpose Register (GPR) numbers
+static int opStackFloatRegisters[OP_STACK_MAX_DEPTH] =
+{
+ 0, 1, 2, 3,
+ 4, 5, 6, 7,
+ 8, 9, 10, 11,
+ 12, 13, 14, 15
+};
+
+static int opStackRegType[OP_STACK_MAX_DEPTH] =
+{
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
// this doesn't have the low order bits set for instructions i'm not using...
typedef enum {
PPC_TDI = 0x08000000,
@@ -200,7 +329,7 @@ typedef enum {
PPC_MCRXR = 0x7c000000,
PPC_LSWX = 0x7c000000,
PPC_LWBRX = 0x7c000000,
- PPC_LFSX = 0x7c000000,
+ PPC_LFSX = 0x7c00042e,
PPC_SRW = 0x7c000430,
PPC_SRD = 0x7c000000,
PPC_TLBSYNC = 0x7c000000,
@@ -213,7 +342,7 @@ typedef enum {
PPC_MFSRIN = 0x7c000000,
PPC_STSWX = 0x7c000000,
PPC_STWBRX = 0x7c000000,
- PPC_STFSX = 0x7c000000,
+ PPC_STFSX = 0x7c00052e,
PPC_STFSUX = 0x7c000000,
PPC_STSWI = 0x7c000000,
PPC_STFDX = 0x7c000000,
@@ -309,6 +438,7 @@ typedef enum {
// the newly generated code
static unsigned *buf;
static int compiledOfs; // in dwords
+static int pass;
// fromt the original bytecode
static byte *code;
@@ -334,83 +464,179 @@ static int Constant1( void ) {
return v;
}
-static void Emit4( int i ) {
+static void Emit4( char *opname, int i ) {
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("\t\t\t%p %s\t%08lx\n",&buf[compiledOfs],opname,i&0x3ffffff);
+ #endif
buf[ compiledOfs ] = i;
compiledOfs++;
}
-static void Inst( int opcode, int destReg, int aReg, int bReg ) {
+static void Inst( char *opname, int opcode, int destReg, int aReg, int bReg ) {
unsigned r;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("\t\t\t%p %s\tr%d,r%d,r%d\n",&buf[compiledOfs],opname,destReg,aReg,bReg);
+ #endif
r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
buf[ compiledOfs ] = r;
compiledOfs++;
}
-static void Inst4( int opcode, int destReg, int aReg, int bReg, int cReg ) {
+static void Inst4( char *opname, int opcode, int destReg, int aReg, int bReg, int cReg ) {
unsigned r;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("\t\t\t%p %s\tr%d,r%d,r%d,r%d\n",&buf[compiledOfs],opname,destReg,aReg,bReg,cReg);
+ #endif
r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) | ( cReg << 6 );
buf[ compiledOfs ] = r;
compiledOfs++;
}
-static void InstImm( int opcode, int destReg, int aReg, int immediate ) {
+static void InstImm( char *opname, int opcode, int destReg, int aReg, int immediate ) {
unsigned r;
if ( immediate > 32767 || immediate < -32768 ) {
Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range, opcode %x,%d,%d", immediate, opcode, destReg, aReg );
}
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("\t\t\t%p %s\tr%d,r%d,0x%x\n",&buf[compiledOfs],opname,destReg,aReg,immediate);
+ #endif
r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
buf[ compiledOfs ] = r;
compiledOfs++;
}
-static void InstImmU( int opcode, int destReg, int aReg, int immediate ) {
+static void InstImmU( char *opname, int opcode, int destReg, int aReg, int immediate ) {
unsigned r;
if ( immediate > 0xffff || immediate < 0 ) {
Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range", immediate );
}
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("\t\t\t%p %s\tr%d,r%d,0x%x\n",&buf[compiledOfs],opname,destReg,aReg,immediate);
+ #endif
r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
buf[ compiledOfs ] = r;
compiledOfs++;
}
-static qboolean rtopped;
static int pop0, pop1, oc0, oc1;
static vm_t *tvm;
static int instruction;
static byte *jused;
-static int pass;
-static void ltop() {
- if (rtopped == qfalse) {
- InstImm( PPC_LWZ, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- }
+static void spillOpStack(int depth)
+{
+ // Store out each register on the operand stack to it's correct location.
+ int i;
+
+ for(i = 0; i < depth; i++)
+ {
+ assert(opStackRegType[i]);
+ assert(opStackRegType[i] == 1);
+ switch(opStackRegType[i])
+ {
+ case 1: // Integer register
+ InstImm( "stw", PPC_STW, opStackIntRegisters[i], R_OPSTACK, i*4+4);
+ break;
+ case 2: // Float register
+ InstImm( "stfs", PPC_STFS, opStackFloatRegisters[i], R_OPSTACK, i*4+4);
+ break;
+ }
+ opStackRegType[i] = 0;
+ }
}
-static void ltopandsecond() {
- if (pass>=0 && buf[compiledOfs-1] == (PPC_STWU | R_TOP<<21 | R_OPSTACK<<16 | 4 ) && jused[instruction]==0 ) {
- compiledOfs--;
- if (!pass) {
- tvm->instructionPointers[instruction] = compiledOfs * 4;
- }
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- } else if (pass>=0 && buf[compiledOfs-1] == (PPC_STW | R_TOP<<21 | R_OPSTACK<<16 | 0 ) && jused[instruction]==0 ) {
- compiledOfs--;
- if (!pass) {
- tvm->instructionPointers[instruction] = compiledOfs * 4;
+static void loadOpStack(int depth)
+{
+ // Back off operand stack pointer and reload all operands.
+// InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -(depth)*4 );
+
+ int i;
+
+ for(i = 0; i < depth; i++)
+ {
+ assert(opStackRegType[i] == 0);
+ // For now we're stuck reloading everything as an integer.
+ opStackLoadInstructionAddr[i] = &buf[compiledOfs];
+ InstImm( "lwz", PPC_LWZ, opStackIntRegisters[i], R_OPSTACK, i*4+4);
+ opStackRegType[i] = 1;
+ }
+}
+
+static void makeFloat(int depth)
+{
+ //assert(opStackRegType[depth] == 1);
+ if(opStackRegType[depth] == 1)
+ {
+ unsigned instruction;
+ unsigned destReg, aReg, bReg, imm;
+
+ if(opStackLoadInstructionAddr[depth])
+ {
+ // Repatch load instruction to use LFS instead of LWZ
+ instruction = *opStackLoadInstructionAddr[depth];
+ // Figure out if it's LWZ or LWZX
+ if((instruction & 0xfc000000) == PPC_LWZ)
+ {
+ //printf("patching LWZ at %p to LFS at depth %ld\n",opStackLoadInstructionAddr[depth],depth);
+ //printf("old instruction: %08lx\n",instruction);
+ // Extract registers
+ destReg = (instruction >> 21) & 31;
+ aReg = (instruction >> 16) & 31;
+ imm = instruction & 0xffff;
+
+ // Calculate correct FP register to use.
+ // THIS ASSUMES REGISTER USAGE FOR THE STACK IS n, n+1, n+2, etc!
+ //printf("old dest: %ld\n",destReg);
+ destReg = (destReg - opStackIntRegisters[0]) + opStackFloatRegisters[0];
+ instruction = PPC_LFS | ( destReg << 21 ) | ( aReg << 16 ) | imm ;
+ //printf("new dest: %ld\n",destReg);
+ //printf("new instruction: %08lx\n",instruction);
+ }
+ else
+ {
+ //printf("patching LWZX at %p to LFSX at depth %ld\n",opStackLoadInstructionAddr[depth],depth);
+ //printf("old instruction: %08lx\n",instruction);
+ // Extract registers
+ destReg = (instruction >> 21) & 31;
+ aReg = (instruction >> 16) & 31;
+ bReg = (instruction >> 11) & 31;
+ // Calculate correct FP register to use.
+ // THIS ASSUMES REGISTER USAGE FOR THE STACK IS n, n+1, n+2, etc!
+ //printf("old dest: %ld\n",destReg);
+ destReg = (destReg - opStackIntRegisters[0]) + opStackFloatRegisters[0];
+ instruction = PPC_LFSX | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
+ //printf("new dest: %ld\n",destReg);
+ //printf("new instruction: %08lx\n",instruction);
+ }
+ *opStackLoadInstructionAddr[depth] = instruction;
+ opStackLoadInstructionAddr[depth] = 0;
+ }
+ else
+ {
+ //printf("doing float constant load at %p for depth %ld\n",&buf[compiledOfs],depth);
+ // It was likely loaded as a constant so we have to save/load it. A more
+ // interesting implementation might be to generate code to do a "PC relative"
+ // load from the VM code region.
+ InstImm( "stw", PPC_STW, opStackIntRegisters[depth], R_OPSTACK, depth*4+4);
+ // For XXX make sure we force enough NOPs to get the load into
+ // another dispatch group to avoid pipeline flush.
+ Inst( "ori", PPC_ORI, 0, 0, 0 );
+ Inst( "ori", PPC_ORI, 0, 0, 0 );
+ Inst( "ori", PPC_ORI, 0, 0, 0 );
+ Inst( "ori", PPC_ORI, 0, 0, 0 );
+ InstImm( "lfs", PPC_LFS, opStackFloatRegisters[depth], R_OPSTACK, depth*4+4);
+ }
+ opStackRegType[depth] = 2;
}
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
- } else {
- ltop(); // get value from opstack
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
- }
- rtopped = qfalse;
}
// TJW: Unused
@@ -422,6 +648,7 @@ static void fltop() {
}
#endif
+#if 0
static void fltopandsecond() {
InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
InstImm( PPC_LFS, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
@@ -429,6 +656,9 @@ static void fltopandsecond() {
rtopped = qfalse;
return;
}
+#endif
+
+#define assertInteger(depth) assert(opStackRegType[depth] == 1)
/*
=================
@@ -440,7 +670,10 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
int maxLength;
int v;
int i;
-
+ int opStackDepth;
+
+ int mainFunction;
+
// set up the into-to-float variables
((int *)itofConvert)[0] = 0x43300000;
((int *)itofConvert)[1] = 0x80000000;
@@ -456,9 +689,10 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
// pointers for branches
for ( pass = -1 ; pass < 2 ; pass++ ) {
- rtopped = qfalse;
// translate all instructions
pc = 0;
+ mainFunction = 0;
+ opStackDepth = 0;
pop0 = 343545;
pop1 = 2443545;
@@ -473,7 +707,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
Emit4( 0 );
#endif
- for ( instruction = 0 ; instruction < header->instructionCount ; instruction++ ) {
+ for ( instruction = 0 ; instruction < header->instructionCount ; instruction++ ) {
if ( compiledOfs*4 > maxLength - 16 ) {
Com_Error( ERR_DROP, "VM_Compile: maxLength exceeded" );
}
@@ -487,651 +721,988 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
case 0:
break;
case OP_BREAK:
- InstImmU( PPC_ADDI, R_TOP, 0, 0 );
- InstImm( PPC_LWZ, R_TOP, R_TOP, 0 ); // *(int *)0 to crash to debugger
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08lx BREAK\n",instruction);
+ #endif
+ InstImmU( "addi", PPC_ADDI, R_TOP, 0, 0 );
+ InstImm( "lwz", PPC_LWZ, R_TOP, R_TOP, 0 ); // *(int *)0 to crash to debugger
break;
case OP_ENTER:
- InstImm( PPC_ADDI, R_STACK, R_STACK, -Constant4() ); // sub R_STACK, R_STACK, imm
- rtopped = qfalse;
+ opStackDepth = 0;
+ v = Constant4();
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x ENTER\t%04x\n",instruction,v);
+ #endif
+ opStackRegType[opStackDepth] = 0;
+ mainFunction++;
+ if(mainFunction == 1)
+ {
+ // Main VM entry point is the first thing we compile, so save off operand stack
+ // registers here. This avoids issues with trying to trick the native compiler
+ // into doing it, and properly matches the PowerPC ABI
+ InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, -OP_STACK_MAX_DEPTH*4 ); // sub R_STACK, R_STACK, imm
+ for(i = 0; i < OP_STACK_MAX_DEPTH; i++)
+ InstImm( "stw", PPC_STW, opStackIntRegisters[i], R_REAL_STACK, i*4);
+ }
+ InstImm( "addi", PPC_ADDI, R_STACK, R_STACK, -v ); // sub R_STACK, R_STACK, imm
break;
case OP_CONST:
v = Constant4();
- if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
- v &= vm->dataMask;
- }
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x CONST\t%08x\n",instruction,v);
+ #endif
+ opStackLoadInstructionAddr[opStackDepth] = 0;
if ( v < 32768 && v >= -32768 ) {
- InstImmU( PPC_ADDI, R_TOP, 0, v & 0xffff );
+ InstImmU( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], 0, v & 0xffff );
} else {
- InstImmU( PPC_ADDIS, R_TOP, 0, (v >> 16)&0xffff );
+ InstImmU( "addis", PPC_ADDIS, opStackIntRegisters[opStackDepth], 0, (v >> 16)&0xffff );
if ( v & 0xffff ) {
- InstImmU( PPC_ORI, R_TOP, R_TOP, v & 0xffff );
+ InstImmU( "ori", PPC_ORI, opStackIntRegisters[opStackDepth], opStackIntRegisters[opStackDepth], v & 0xffff );
}
}
- if (code[pc] == OP_LOAD4) {
- Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- pc++;
- instruction++;
- } else if (code[pc] == OP_LOAD2) {
- Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- pc++;
- instruction++;
- } else if (code[pc] == OP_LOAD1) {
- Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- pc++;
- instruction++;
- }
- if (code[pc] == OP_STORE4) {
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- pc++;
- instruction++;
- rtopped = qfalse;
- break;
- } else if (code[pc] == OP_STORE2) {
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- pc++;
- instruction++;
- rtopped = qfalse;
- break;
- } else if (code[pc] == OP_STORE1) {
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- pc++;
- instruction++;
- rtopped = qfalse;
- break;
- }
+ opStackRegType[opStackDepth] = 1;
+ opStackDepth += 1;
if (code[pc] == OP_JUMP) {
jused[v] = 1;
}
- InstImm( PPC_STWU, R_TOP, R_OPSTACK, 4 );
- rtopped = qtrue;
break;
case OP_LOCAL:
- oc0 = oc1;
oc1 = Constant4();
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LOCAL\t%08x\n",instruction,oc1);
+ #endif
if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
oc1 &= vm->dataMask;
}
- InstImm( PPC_ADDI, R_TOP, R_STACK, oc1 );
- if (code[pc] == OP_LOAD4) {
- Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- pc++;
- instruction++;
- } else if (code[pc] == OP_LOAD2) {
- Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- pc++;
- instruction++;
- } else if (code[pc] == OP_LOAD1) {
- Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- pc++;
- instruction++;
- }
- if (code[pc] == OP_STORE4) {
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- pc++;
- instruction++;
- rtopped = qfalse;
- break;
- } else if (code[pc] == OP_STORE2) {
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- pc++;
- instruction++;
- rtopped = qfalse;
- break;
- } else if (code[pc] == OP_STORE1) {
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- pc++;
- instruction++;
- rtopped = qfalse;
- break;
- }
- InstImm( PPC_STWU, R_TOP, R_OPSTACK, 4 );
- rtopped = qtrue;
+ InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], R_STACK, oc1 );
+ opStackRegType[opStackDepth] = 1;
+ opStackLoadInstructionAddr[opStackDepth] = 0;
+ opStackDepth += 1;
break;
case OP_ARG:
- ltop(); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- InstImm( PPC_ADDI, R_EA, R_STACK, Constant1() ); // location to put it
- Inst( PPC_STWX, R_TOP, R_EA, R_MEMBASE );
- rtopped = qfalse;
+ v = Constant1();
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x ARG \t%08x\n",instruction,v);
+ #endif
+ InstImm( "addi", PPC_ADDI, R_EA, R_STACK, v ); // location to put it
+ if(opStackRegType[opStackDepth-1] == 1)
+ Inst( "stwx", PPC_STWX, opStackIntRegisters[opStackDepth-1], R_EA, R_MEMBASE );
+ else
+ Inst( "stfsx", PPC_STFSX, opStackFloatRegisters[opStackDepth-1], R_EA, R_MEMBASE );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
+
break;
case OP_CALL:
- Inst( PPC_MFSPR, R_SECOND, 8, 0 ); // move from link register
- InstImm( PPC_STWU, R_SECOND, R_REAL_STACK, -16 ); // save off the old return address
-
- Inst( PPC_MTSPR, R_ASMCALL, 9, 0 ); // move to count register
- Inst( PPC_BCCTR | 1, 20, 0, 0 ); // jump and link to the count register
-
- InstImm( PPC_LWZ, R_SECOND, R_REAL_STACK, 0 ); // fetch the old return address
- InstImm( PPC_ADDI, R_REAL_STACK, R_REAL_STACK, 16 );
- Inst( PPC_MTSPR, R_SECOND, 8, 0 ); // move to link register
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x CALL\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assert(opStackDepth > 0);
+ Inst( "mflr", PPC_MFSPR, R_SECOND, 8, 0 ); // move from link register
+ InstImm( "stwu", PPC_STWU, R_SECOND, R_REAL_STACK, -16 ); // save off the old return address
+
+ // Spill operand stack registers.
+ spillOpStack(opStackDepth);
+
+ // We need to leave R_OPSTACK pointing to the top entry on the stack, which is the call address.
+ // It will be consumed (and R4 decremented) by the AsmCall code.
+ InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, opStackDepth*4);
+
+ Inst( "mtctr", PPC_MTSPR, R_ASMCALL, 9, 0 ); // move to count register
+ Inst( "bctrl", PPC_BCCTR | 1, 20, 0, 0 ); // jump and link to the count register
+
+ // R4 now points to the top of the operand stack, which has the return value in it. We want to
+ // back off the pointer to point to the base of our local operand stack and then reload the stack.
+
+ InstImm("addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -opStackDepth*4);
+
+ // Reload operand stack.
+ loadOpStack(opStackDepth);
+
+ InstImm( "lwz", PPC_LWZ, R_SECOND, R_REAL_STACK, 0 ); // fetch the old return address
+ InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, 16 );
+ Inst( "mtlr", PPC_MTSPR, R_SECOND, 8, 0 ); // move to link register
break;
case OP_PUSH:
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, 4 );
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x PUSH\n",instruction);
+ #endif
+ opStackRegType[opStackDepth] = 1; // Garbage int value.
+ opStackDepth += 1;
break;
case OP_POP:
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x POP\n",instruction);
+ #endif
+ opStackDepth -= 1;
+ opStackRegType[opStackDepth] = 0; // ??
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
break;
case OP_LEAVE:
- InstImm( PPC_ADDI, R_STACK, R_STACK, Constant4() ); // add R_STACK, R_STACK, imm
- Inst( PPC_BCLR, 20, 0, 0 ); // branch unconditionally to link register
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LEAVE\n",instruction);
+ #endif
+ assert(opStackDepth == 1);
+ assert(opStackRegType[0] != 0);
+ // Save return value onto top of op stack. We also have to increment R_OPSTACK
+ switch(opStackRegType[0])
+ {
+ case 1: // Integer register
+ InstImm( "stw", PPC_STWU, opStackIntRegisters[0], R_OPSTACK, 4);
+ break;
+ case 2: // Float register
+ InstImm( "stfs", PPC_STFSU, opStackFloatRegisters[0], R_OPSTACK, 4);
+ break;
+ }
+ InstImm( "addi", PPC_ADDI, R_STACK, R_STACK, Constant4() ); // add R_STACK, R_STACK, imm
+ if(mainFunction == 1)
+ {
+ for(i = 0; i < OP_STACK_MAX_DEPTH; i++)
+ InstImm( "lwz", PPC_LWZ, opStackIntRegisters[i], R_REAL_STACK, i*4);
+ InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, OP_STACK_MAX_DEPTH*4 );
+ }
+ opStackDepth--;
+ opStackRegType[opStackDepth] = 0;
+ opStackLoadInstructionAddr[opStackDepth] = 0;
+ Inst( "blr", PPC_BCLR, 20, 0, 0 ); // branch unconditionally to link register
break;
case OP_LOAD4:
- ltop(); // get value from opstack
- //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP ); // mask it
- Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LOAD4\n",instruction);
+ #endif
+ // We should try to figure out whether to use LWZX or LFSX based
+ // on some kind of code analysis after subsequent passes. I think what
+ // we could do is store the compiled load instruction address along with
+ // the register type. When we hit the first mismatched operator, we go back
+ // and patch the load. Since LCC's operand stack should be at 0 depth by the
+ // time we hit a branch, this should work fairly well. FIXME FIXME FIXME.
+ assertInteger(opStackDepth-1);
+ opStackLoadInstructionAddr[opStackDepth-1] = &buf[ compiledOfs ];
+ Inst( "lwzx", PPC_LWZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
+ opStackRegType[opStackDepth-1] = 1;
break;
case OP_LOAD2:
- ltop(); // get value from opstack
- //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP ); // mask it
- Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LOAD2\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ Inst( "lhzx", PPC_LHZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
+ opStackRegType[opStackDepth-1] = 1;
break;
case OP_LOAD1:
- ltop(); // get value from opstack
- //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP ); // mask it
- Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LOAD1\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ Inst( "lbzx", PPC_LBZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
+ opStackRegType[opStackDepth-1] = 1;
break;
case OP_STORE4:
- ltopandsecond(); // get value from opstack
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x STORE4\n",instruction);
+ #endif
+ assertInteger(opStackDepth-2);
+ if(opStackRegType[opStackDepth-1] == 1)
+ Inst( "stwx", PPC_STWX, opStackIntRegisters[opStackDepth-1],
+ opStackIntRegisters[opStackDepth-2], R_MEMBASE ); // store from memory base
+ else
+ Inst( "stfsx", PPC_STFSX, opStackFloatRegisters[opStackDepth-1],
+ opStackIntRegisters[opStackDepth-2], R_MEMBASE ); // store from memory base
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
break;
case OP_STORE2:
- ltopandsecond(); // get value from opstack
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x STORE2\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "sthx", PPC_STHX, opStackIntRegisters[opStackDepth-1],
+ opStackIntRegisters[opStackDepth-2], R_MEMBASE ); // store from memory base
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
break;
case OP_STORE1:
- ltopandsecond(); // get value from opstack
- //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
- Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x STORE1\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "stbx", PPC_STBX, opStackIntRegisters[opStackDepth-1],
+ opStackIntRegisters[opStackDepth-2], R_MEMBASE ); // store from memory base
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
break;
case OP_EQ:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMP, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x EQ\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 4, 2, 8 );
+ InstImm( "bc", PPC_BC, 4, 2, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (v&0x3ffffff) );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (v&0x3ffffff) );
break;
case OP_NE:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMP, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x NE\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 12, 2, 8 );
+ InstImm( "bc", PPC_BC, 12, 2, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 4, 2, v );
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 4, 2, v );
- rtopped = qfalse;
break;
case OP_LTI:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMP, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LTI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 4, 0, 8 );
+ InstImm( "bc", PPC_BC, 4, 0, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 12, 0, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 12, 0, v );
break;
case OP_LEI:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMP, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LEI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 12, 1, 8 );
+ InstImm( "bc", PPC_BC, 12, 1, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 4, 1, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 4, 1, v );
break;
case OP_GTI:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMP, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x GTI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 4, 1, 8 );
+ InstImm( "bc", PPC_BC, 4, 1, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 12, 1, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 12, 1, v );
break;
case OP_GEI:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMP, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x GEI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 12, 0, 8 );
+ InstImm( "bc", PPC_BC, 12, 0, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 4, 0, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 4, 0, v );
break;
case OP_LTU:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LTU\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 4, 0, 8 );
+ InstImm( "bc", PPC_BC, 4, 0, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 12, 0, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 12, 0, v );
break;
case OP_LEU:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LEU\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 12, 1, 8 );
+ InstImm( "bc", PPC_BC, 12, 1, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 4, 1, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 4, 1, v );
break;
case OP_GTU:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x GTU\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 4, 1, 8 );
+ InstImm( "bc", PPC_BC, 4, 1, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 12, 1, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 12, 1, v );
break;
case OP_GEU:
- ltopandsecond(); // get value from opstack
- Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x GEU\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 12, 0, 8 );
+ InstImm( "bc", PPC_BC, 12, 0, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 4, 0, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 4, 0, v );
break;
case OP_EQF:
- fltopandsecond(); // get value from opstack
- Inst( PPC_FCMPU, 0, R_TOP, R_SECOND );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x EQF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 4, 2, 8 );
+ InstImm( "bc", PPC_BC, 4, 2, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 12, 2, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 12, 2, v );
break;
case OP_NEF:
- fltopandsecond(); // get value from opstack
- Inst( PPC_FCMPU, 0, R_TOP, R_SECOND );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x NEF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 12, 2, 8 );
+ InstImm( "bc", PPC_BC, 12, 2, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 4, 2, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 4, 2, v );
break;
case OP_LTF:
- fltopandsecond(); // get value from opstack
- Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LTF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 4, 0, 8 );
+ InstImm( "bc", PPC_BC, 4, 0, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 12, 0, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 12, 0, v );
break;
case OP_LEF:
- fltopandsecond(); // get value from opstack
- Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LEF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 12, 1, 8 );
+ InstImm( "bc", PPC_BC, 12, 1, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 4, 1, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 4, 1, v );
break;
case OP_GTF:
- fltopandsecond(); // get value from opstack
- Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x GTF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 4, 1, 8 );
+ InstImm( "bc", PPC_BC, 4, 1, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 12, 1, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 12, 1, v );
break;
case OP_GEF:
- fltopandsecond(); // get value from opstack
- Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x GEF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
i = Constant4();
jused[i] = 1;
- InstImm( PPC_BC, 12, 0, 8 );
+ InstImm( "bc", PPC_BC, 12, 0, 8 );
if ( pass==1 ) {
v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
} else {
v = 0;
}
- Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( PPC_BC, 4, 0, v );
- rtopped = qfalse;
+ Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
+// InstImm( "bc", PPC_BC, 4, 0, v );
break;
case OP_NEGI:
- ltop(); // get value from opstack
- InstImm( PPC_SUBFIC, R_TOP, R_TOP, 0 );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x NEGI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ InstImm( "subfic", PPC_SUBFIC, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
break;
case OP_ADD:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_ADD, R_TOP, R_TOP, R_SECOND );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x ADD\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_SUB:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_SUBF, R_TOP, R_TOP, R_SECOND );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x SUB\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_DIVI:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_DIVW, R_TOP, R_SECOND, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x DIVI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "divw", PPC_DIVW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_DIVU:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_DIVWU, R_TOP, R_SECOND, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x DIVU\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "divwu", PPC_DIVWU, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_MODI:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_DIVW, R_EA, R_SECOND, R_TOP );
- Inst( PPC_MULLW, R_EA, R_TOP, R_EA );
- Inst( PPC_SUBF, R_TOP, R_EA, R_SECOND );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x MODI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "divw", PPC_DIVW, R_EA, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ Inst( "mullw", PPC_MULLW, R_EA, opStackIntRegisters[opStackDepth-1], R_EA );
+ Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], R_EA, opStackIntRegisters[opStackDepth-2] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_MODU:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_DIVWU, R_EA, R_SECOND, R_TOP );
- Inst( PPC_MULLW, R_EA, R_TOP, R_EA );
- Inst( PPC_SUBF, R_TOP, R_EA, R_SECOND );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x MODU\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "divwu", PPC_DIVWU, R_EA, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ Inst( "mullw", PPC_MULLW, R_EA, opStackIntRegisters[opStackDepth-1], R_EA );
+ Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], R_EA, opStackIntRegisters[opStackDepth-2] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_MULI:
case OP_MULU:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_MULLW, R_TOP, R_SECOND, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x MULI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "mullw", PPC_MULLW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_BAND:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_AND, R_SECOND, R_TOP, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x BAND\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "and", PPC_AND, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_BOR:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_OR, R_SECOND, R_TOP, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x BOR\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "or", PPC_OR, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_BXOR:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_XOR, R_SECOND, R_TOP, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x BXOR\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "xor", PPC_XOR, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_BCOM:
- ltop(); // get value from opstack
- Inst( PPC_NOR, R_TOP, R_TOP, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x BCOM\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ Inst( "nor", PPC_NOR, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1] );
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
break;
case OP_LSH:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_SLW, R_SECOND, R_TOP, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x LSH\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "slw", PPC_SLW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_RSHI:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_SRAW, R_SECOND, R_TOP, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x RSHI\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "sraw", PPC_SRAW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_RSHU:
- ltop(); // get value from opstack
- InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_SRW, R_SECOND, R_TOP, R_TOP );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x RSHU\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ Inst( "srw", PPC_SRW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_NEGF:
- InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- Inst( PPC_FNEG, R_TOP, 0, R_TOP );
- InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x NEGF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ Inst( "fneg", PPC_FNEG, opStackFloatRegisters[opStackDepth-1], 0, opStackFloatRegisters[opStackDepth-1] );
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
break;
case OP_ADDF:
- InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_LFSU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_FADDS, R_TOP, R_SECOND, R_TOP );
- InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x ADDF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fadds", PPC_FADDS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_SUBF:
- InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_LFSU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_FSUBS, R_TOP, R_SECOND, R_TOP );
- InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x SUBF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fsubs", PPC_FSUBS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_DIVF:
- InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_LFSU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst( PPC_FDIVS, R_TOP, R_SECOND, R_TOP );
- InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x DIVF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst( "fdivs", PPC_FDIVS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_MULF:
- InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_LFSU, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- Inst4( PPC_FMULS, R_TOP, R_SECOND, 0, R_TOP );
- InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x MULF\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+ makeFloat(opStackDepth-2);
+ Inst4( "fmuls", PPC_FMULS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], 0, opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
case OP_CVIF:
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x CVIF\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ //makeInteger(opStackDepth-1);
v = (int)&itofConvert;
- InstImmU( PPC_ADDIS, R_EA, 0, (v >> 16)&0xffff );
- InstImmU( PPC_ORI, R_EA, R_EA, v & 0xffff );
- InstImm( PPC_LWZ, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- InstImmU( PPC_XORIS, R_TOP, R_TOP, 0x8000 );
- InstImm( PPC_STW, R_TOP, R_EA, 12 );
- InstImm( PPC_LFD, R_TOP, R_EA, 0 );
- InstImm( PPC_LFD, R_SECOND, R_EA, 8 );
- Inst( PPC_FSUB, R_TOP, R_SECOND, R_TOP );
+ InstImmU( "addis", PPC_ADDIS, R_EA, 0, (v >> 16)&0xffff );
+ InstImmU( "ori", PPC_ORI, R_EA, R_EA, v & 0xffff );
+ InstImmU( "xoris", PPC_XORIS, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0x8000 );
+ InstImm( "stw", PPC_STW, opStackIntRegisters[opStackDepth-1], R_EA, 12 );
+ InstImm( "lfd", PPC_LFD, opStackFloatRegisters[opStackDepth-1], R_EA, 0 );
+ Inst( "ori", PPC_ORI, 0, 0, 0);
+ Inst( "ori", PPC_ORI, 0, 0, 0);
+ Inst( "ori", PPC_ORI, 0, 0, 0);
+ InstImm( "lfd", PPC_LFD, 13, R_EA, 8 );
+ Inst( "fsub", PPC_FSUB, opStackFloatRegisters[opStackDepth-1], 13, opStackFloatRegisters[opStackDepth-1] );
+ opStackRegType[opStackDepth-1] = 2;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
// Inst( PPC_FRSP, R_TOP, 0, R_TOP );
- InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 ); // save value to opstack
- rtopped = qfalse;
break;
case OP_CVFI:
- InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- Inst( PPC_FCTIWZ, R_TOP, 0, R_TOP );
- Inst( PPC_STFIWX, R_TOP, 0, R_OPSTACK ); // save value to opstack
- rtopped = qfalse;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x CVFI\n",instruction);
+ #endif
+ makeFloat(opStackDepth-1);
+
+ InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, opStackDepth*4);
+
+ Inst( "fctiwz", PPC_FCTIWZ, opStackFloatRegisters[opStackDepth-1], 0, opStackFloatRegisters[opStackDepth-1] );
+ Inst( "stfiwx", PPC_STFIWX, opStackFloatRegisters[opStackDepth-1], 0, R_OPSTACK ); // save value to opstack (dummy area now)
+ Inst( "ori", PPC_ORI, 0, 0, 0);
+ Inst( "ori", PPC_ORI, 0, 0, 0);
+ Inst( "ori", PPC_ORI, 0, 0, 0);
+ Inst( "ori", PPC_ORI, 0, 0, 0);
+ InstImm( "lwz", PPC_LWZ, opStackIntRegisters[opStackDepth-1], R_OPSTACK, 0 );
+
+ InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -opStackDepth*4);
+
+ opStackRegType[opStackDepth-1] = 1;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
break;
case OP_SEX8:
- ltop(); // get value from opstack
- Inst( PPC_EXTSB, R_TOP, R_TOP, 0 );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x SEX8\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ Inst( "extsb", PPC_EXTSB, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
break;
case OP_SEX16:
- ltop(); // get value from opstack
- Inst( PPC_EXTSH, R_TOP, R_TOP, 0 );
- InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
- rtopped = qtrue;
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x SEX16\n",instruction);
+ #endif
+ assertInteger(opStackDepth-1);
+ Inst( "extsh", PPC_EXTSH, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
break;
case OP_BLOCK_COPY:
v = Constant4() >> 2;
- ltop(); // source
- InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 ); // dest
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
- InstImmU( PPC_ADDI, R_EA, 0, v ); // count
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x BLOCK_COPY\t%08lx\n",instruction,v<<2);
+ #endif
+ assert(opStackDepth >= 2);
+ assertInteger(opStackDepth-1);
+ assertInteger(opStackDepth-2);
+ InstImmU( "addi", PPC_ADDI, R_EA, 0, v ); // count
// FIXME: range check
- Inst( PPC_MTSPR, R_EA, 9, 0 ); // move to count register
-
- Inst( PPC_ADD, R_TOP, R_TOP, R_MEMBASE );
- InstImm( PPC_ADDI, R_TOP, R_TOP, -4 );
- Inst( PPC_ADD, R_SECOND, R_SECOND, R_MEMBASE );
- InstImm( PPC_ADDI, R_SECOND, R_SECOND, -4 );
-
- InstImm( PPC_LWZU, R_EA, R_TOP, 4 ); // source
- InstImm( PPC_STWU, R_EA, R_SECOND, 4 ); // dest
- Inst( PPC_BC | 0xfff8 , 16, 0, 0 ); // loop
- rtopped = qfalse;
+ Inst( "mtctr", PPC_MTSPR, R_EA, 9, 0 ); // move to count register
+
+ Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );
+ InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], -4 );
+ Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], R_MEMBASE );
+ InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], -4 );
+
+ InstImm( "lwzu", PPC_LWZU, R_EA, opStackIntRegisters[opStackDepth-1], 4 ); // source
+ InstImm( "stwu", PPC_STWU, R_EA, opStackIntRegisters[opStackDepth-2], 4 ); // dest
+ Inst( "b", PPC_BC | 0xfff8 , 16, 0, 0 ); // loop
+ opStackRegType[opStackDepth-1] = 0;
+ opStackRegType[opStackDepth-2] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-2] = 0;
+ opStackDepth -= 2;
break;
case OP_JUMP:
- ltop(); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
- Inst( PPC_RLWINM | ( 29 << 1 ), R_TOP, R_TOP, 2 );
+ #if DEBUG_VM
+ if(pass == 1)
+ printf("%08x JUMP\n",instruction);
+ #endif
+ assert(opStackDepth == 1);
+ assertInteger(opStackDepth-1);
+
+ Inst( "rlwinm", PPC_RLWINM | ( 29 << 1 ), opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 2 );
// FIXME: range check
- Inst( PPC_LWZX, R_TOP, R_TOP, R_INSTRUCTIONS );
- Inst( PPC_MTSPR, R_TOP, 9, 0 ); // move to count register
- Inst( PPC_BCCTR, 20, 0, 0 ); // jump to the count register
- rtopped = qfalse;
+ Inst( "lwzx", PPC_LWZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_INSTRUCTIONS );
+ Inst( "mtctr", PPC_MTSPR, opStackIntRegisters[opStackDepth-1], 9, 0 ); // move to count register
+ Inst( "bctr", PPC_BCCTR, 20, 0, 0 ); // jump to the count register
+ opStackRegType[opStackDepth-1] = 0;
+ opStackLoadInstructionAddr[opStackDepth-1] = 0;
+ opStackDepth -= 1;
break;
default:
Com_Error( ERR_DROP, "VM_CompilePPC: bad opcode %i at instruction %i, offset %i", op, instruction, pc );
}
pop0 = pop1;
pop1 = op;
+ assert(opStackDepth >= 0);
+ assert(opStackDepth < OP_STACK_MAX_DEPTH);
+
+ //printf("%4d\t%s\n",opStackDepth,opnames[op]);
}
Com_Printf( "VM file %s pass %d compiled to %i bytes of code\n", vm->name, (pass+1), compiledOfs*4 );
@@ -1141,16 +1712,33 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
vm->codeLength = compiledOfs * 4;
vm->codeBase = Hunk_Alloc( vm->codeLength, h_low );
Com_Memcpy( vm->codeBase, buf, vm->codeLength );
+
+ //printf("codeBase: %p\n",vm->codeBase);
+
Z_Free( buf );
// offset all the instruction pointers for the new location
for ( i = 0 ; i < header->instructionCount ; i++ ) {
vm->instructionPointers[i] += (int)vm->codeBase;
+ //printf("%08x %08lx\n",i,vm->instructionPointers[i]);
}
// go back over it in place now to fixup reletive jump targets
buf = (unsigned *)vm->codeBase;
- }
+ } else if ( pass == 1 ) {
+ #ifdef MACOS_X
+ // On Mac OS X, the following library routine clears the instruction cache for generated code
+ MakeDataExecutable(vm->codeBase, vm->codeLength);
+ #else
+ #warning Need to clear the instruction cache for generated code
+ #endif
+ }
+ }
+ if(0)
+ {
+ char buf[256];
+ printf("wait..\n");
+ gets(buf);
}
Z_Free( jused );
}
@@ -1170,6 +1758,9 @@ int VM_CallCompiled( vm_t *vm, int *args ) {
currentVM = vm;
+ //printf("VM_CallCompiled: %p %08lx %08lx %08lx\n",
+ // vm, args[0],args[1],args[2]);
+
// interpret the code
vm->currentlyInterpreting = qtrue;
@@ -1194,6 +1785,7 @@ int VM_CallCompiled( vm_t *vm, int *args ) {
*(int *)&image[ programStack + 4 ] = 0; // return stack
*(int *)&image[ programStack ] = -1; // will terminate the loop on return
+ // Cheesy... manually save registers used by VM call...
// off we go into generated code...
// the PPC calling standard says the parms will all go into R3 - R11, so
// no special asm code is needed here
@@ -1246,7 +1838,7 @@ asm (
#if defined(MACOS_X) && defined(__OPTIMIZE__)
// On Mac OS X, gcc doesn't push a frame when we are optimized, so trying to tear it down results in grave disorder.
-#warning Mac OS X optimization on, not popping GCC AsmCall frame
+//#warning Mac OS X optimization on, not popping GCC AsmCall frame
#else
// Mac OS X Server and unoptimized compiles include a GCC AsmCall frame
asm (
@@ -1309,7 +1901,7 @@ asm (
// save off the return value
" stwu r12,4(r4) \n" // RG_TOP, 0(RG_OPSTACK)
- // GCC adds its own prolog / epilog code
+ // GCC adds its own prolog / epliog code
);
}
#else
diff --git a/src/qcommon/vm_ppc_new.c b/src/qcommon/vm_ppc_new.c
deleted file mode 100644
index 79fc506f..00000000
--- a/src/qcommon/vm_ppc_new.c
+++ /dev/null
@@ -1,2072 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-Copyright (C) 2000-2006 Tim Angus
-
-This file is part of Tremulous.
-
-Tremulous 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.
-
-Tremulous 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 Tremulous; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// vm_ppc.c
-// ppc dynamic compiler
-
-#include "vm_local.h"
-
-#ifdef MACOS_X
-#include <CoreServices/CoreServices.h>
-#endif
-
-#define DEBUG_VM 0
-
-#if DEBUG_VM
-static char *opnames[256] = {
- "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",
- "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"
-};
-#endif
-
-typedef enum {
- R_REAL_STACK = 1,
- // registers 3-11 are the parameter passing registers
-
- // state
- R_STACK = 3, // local
- R_OPSTACK, // global
-
- // constants
- R_MEMBASE, // global
- R_MEMMASK,
- R_ASMCALL, // global
- R_INSTRUCTIONS, // global
- R_NUM_INSTRUCTIONS, // global
- R_CVM, // currentVM
-
- // temps
- R_TOP = 11,
- R_SECOND = 12,
- R_EA = 2 // effective address calculation
-
-} regNums_t;
-
-#define RG_REAL_STACK r1
-#define RG_STACK r3
-#define RG_OPSTACK r4
-#define RG_MEMBASE r5
-#define RG_MEMMASK r6
-#define RG_ASMCALL r7
-#define RG_INSTRUCTIONS r8
-#define RG_NUM_INSTRUCTIONS r9
-#define RG_CVM r10
-#define RG_TOP r12
-#define RG_SECOND r13
-#define RG_EA r14
-
-// The deepest value I saw in the Quake3 games was 9.
-#define OP_STACK_MAX_DEPTH 16
-
-// These are all volatile and thus must be saved upon entry to the VM code.
-// NOTE: These are General Purpose Registers (GPR) numbers like the
-// R_ definitions in the regNums_t enum above (31 is the max)
-static int opStackIntRegisters[OP_STACK_MAX_DEPTH] =
-{
- 16, 17, 18, 19,
- 20, 21, 22, 23,
- 24, 25, 26, 27,
- 28, 29, 30, 31
-};
-
-static unsigned int *opStackLoadInstructionAddr[OP_STACK_MAX_DEPTH];
-
-// We use different registers for the floating point
-// operand stack (these are volatile in the PPC ABI)
-// NOTE: these are Floating Point Register (FPR) numbers, not
-// General Purpose Register (GPR) numbers
-static int opStackFloatRegisters[OP_STACK_MAX_DEPTH] =
-{
- 0, 1, 2, 3,
- 4, 5, 6, 7,
- 8, 9, 10, 11,
- 12, 13, 14, 15
-};
-
-static int opStackRegType[OP_STACK_MAX_DEPTH] =
-{
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0
-};
-
-// this doesn't have the low order bits set for instructions i'm not using...
-typedef enum {
- PPC_TDI = 0x08000000,
- PPC_TWI = 0x0c000000,
- PPC_MULLI = 0x1c000000,
- PPC_SUBFIC = 0x20000000,
- PPC_CMPI = 0x28000000,
- PPC_CMPLI = 0x2c000000,
- PPC_ADDIC = 0x30000000,
- PPC_ADDIC_ = 0x34000000,
- PPC_ADDI = 0x38000000,
- PPC_ADDIS = 0x3c000000,
- PPC_BC = 0x40000000,
- PPC_SC = 0x44000000,
- PPC_B = 0x48000000,
-
- PPC_MCRF = 0x4c000000,
- PPC_BCLR = 0x4c000020,
- PPC_RFID = 0x4c000000,
- PPC_CRNOR = 0x4c000000,
- PPC_RFI = 0x4c000000,
- PPC_CRANDC = 0x4c000000,
- PPC_ISYNC = 0x4c000000,
- PPC_CRXOR = 0x4c000000,
- PPC_CRNAND = 0x4c000000,
- PPC_CREQV = 0x4c000000,
- PPC_CRORC = 0x4c000000,
- PPC_CROR = 0x4c000000,
-//------------
- PPC_BCCTR = 0x4c000420,
- PPC_RLWIMI = 0x50000000,
- PPC_RLWINM = 0x54000000,
- PPC_RLWNM = 0x5c000000,
- PPC_ORI = 0x60000000,
- PPC_ORIS = 0x64000000,
- PPC_XORI = 0x68000000,
- PPC_XORIS = 0x6c000000,
- PPC_ANDI_ = 0x70000000,
- PPC_ANDIS_ = 0x74000000,
- PPC_RLDICL = 0x78000000,
- PPC_RLDICR = 0x78000000,
- PPC_RLDIC = 0x78000000,
- PPC_RLDIMI = 0x78000000,
- PPC_RLDCL = 0x78000000,
- PPC_RLDCR = 0x78000000,
- PPC_CMP = 0x7c000000,
- PPC_TW = 0x7c000000,
- PPC_SUBFC = 0x7c000010,
- PPC_MULHDU = 0x7c000000,
- PPC_ADDC = 0x7c000014,
- PPC_MULHWU = 0x7c000000,
- PPC_MFCR = 0x7c000000,
- PPC_LWAR = 0x7c000000,
- PPC_LDX = 0x7c000000,
- PPC_LWZX = 0x7c00002e,
- PPC_SLW = 0x7c000030,
- PPC_CNTLZW = 0x7c000000,
- PPC_SLD = 0x7c000000,
- PPC_AND = 0x7c000038,
- PPC_CMPL = 0x7c000040,
- PPC_SUBF = 0x7c000050,
- PPC_LDUX = 0x7c000000,
-//------------
- PPC_DCBST = 0x7c000000,
- PPC_LWZUX = 0x7c00006c,
- PPC_CNTLZD = 0x7c000000,
- PPC_ANDC = 0x7c000000,
- PPC_TD = 0x7c000000,
- PPC_MULHD = 0x7c000000,
- PPC_MULHW = 0x7c000000,
- PPC_MTSRD = 0x7c000000,
- PPC_MFMSR = 0x7c000000,
- PPC_LDARX = 0x7c000000,
- PPC_DCBF = 0x7c000000,
- PPC_LBZX = 0x7c0000ae,
- PPC_NEG = 0x7c000000,
- PPC_MTSRDIN = 0x7c000000,
- PPC_LBZUX = 0x7c000000,
- PPC_NOR = 0x7c0000f8,
- PPC_SUBFE = 0x7c000000,
- PPC_ADDE = 0x7c000000,
- PPC_MTCRF = 0x7c000000,
- PPC_MTMSR = 0x7c000000,
- PPC_STDX = 0x7c000000,
- PPC_STWCX_ = 0x7c000000,
- PPC_STWX = 0x7c00012e,
- PPC_MTMSRD = 0x7c000000,
- PPC_STDUX = 0x7c000000,
- PPC_STWUX = 0x7c00016e,
- PPC_SUBFZE = 0x7c000000,
- PPC_ADDZE = 0x7c000000,
- PPC_MTSR = 0x7c000000,
- PPC_STDCX_ = 0x7c000000,
- PPC_STBX = 0x7c0001ae,
- PPC_SUBFME = 0x7c000000,
- PPC_MULLD = 0x7c000000,
-//------------
- PPC_ADDME = 0x7c000000,
- PPC_MULLW = 0x7c0001d6,
- PPC_MTSRIN = 0x7c000000,
- PPC_DCBTST = 0x7c000000,
- PPC_STBUX = 0x7c000000,
- PPC_ADD = 0x7c000214,
- PPC_DCBT = 0x7c000000,
- PPC_LHZX = 0x7c00022e,
- PPC_EQV = 0x7c000000,
- PPC_TLBIE = 0x7c000000,
- PPC_ECIWX = 0x7c000000,
- PPC_LHZUX = 0x7c000000,
- PPC_XOR = 0x7c000278,
- PPC_MFSPR = 0x7c0002a6,
- PPC_LWAX = 0x7c000000,
- PPC_LHAX = 0x7c000000,
- PPC_TLBIA = 0x7c000000,
- PPC_MFTB = 0x7c000000,
- PPC_LWAUX = 0x7c000000,
- PPC_LHAUX = 0x7c000000,
- PPC_STHX = 0x7c00032e,
- PPC_ORC = 0x7c000338,
- PPC_SRADI = 0x7c000000,
- PPC_SLBIE = 0x7c000000,
- PPC_ECOWX = 0x7c000000,
- PPC_STHUX = 0x7c000000,
- PPC_OR = 0x7c000378,
- PPC_DIVDU = 0x7c000000,
- PPC_DIVWU = 0x7c000396,
- PPC_MTSPR = 0x7c0003a6,
- PPC_DCBI = 0x7c000000,
- PPC_NAND = 0x7c000000,
- PPC_DIVD = 0x7c000000,
-//------------
- PPC_DIVW = 0x7c0003d6,
- PPC_SLBIA = 0x7c000000,
- PPC_MCRXR = 0x7c000000,
- PPC_LSWX = 0x7c000000,
- PPC_LWBRX = 0x7c000000,
- PPC_LFSX = 0x7c00042e,
- PPC_SRW = 0x7c000430,
- PPC_SRD = 0x7c000000,
- PPC_TLBSYNC = 0x7c000000,
- PPC_LFSUX = 0x7c000000,
- PPC_MFSR = 0x7c000000,
- PPC_LSWI = 0x7c000000,
- PPC_SYNC = 0x7c000000,
- PPC_LFDX = 0x7c000000,
- PPC_LFDUX = 0x7c000000,
- PPC_MFSRIN = 0x7c000000,
- PPC_STSWX = 0x7c000000,
- PPC_STWBRX = 0x7c000000,
- PPC_STFSX = 0x7c00052e,
- PPC_STFSUX = 0x7c000000,
- PPC_STSWI = 0x7c000000,
- PPC_STFDX = 0x7c000000,
- PPC_DCBA = 0x7c000000,
- PPC_STFDUX = 0x7c000000,
- PPC_LHBRX = 0x7c000000,
- PPC_SRAW = 0x7c000630,
- PPC_SRAD = 0x7c000000,
- PPC_SRAWI = 0x7c000000,
- PPC_EIEIO = 0x7c000000,
- PPC_STHBRX = 0x7c000000,
- PPC_EXTSH = 0x7c000734,
- PPC_EXTSB = 0x7c000774,
- PPC_ICBI = 0x7c000000,
-//------------
- PPC_STFIWX = 0x7c0007ae,
- PPC_EXTSW = 0x7c000000,
- PPC_DCBZ = 0x7c000000,
- PPC_LWZ = 0x80000000,
- PPC_LWZU = 0x84000000,
- PPC_LBZ = 0x88000000,
- PPC_LBZU = 0x8c000000,
- PPC_STW = 0x90000000,
- PPC_STWU = 0x94000000,
- PPC_STB = 0x98000000,
- PPC_STBU = 0x9c000000,
- PPC_LHZ = 0xa0000000,
- PPC_LHZU = 0xa4000000,
- PPC_LHA = 0xa8000000,
- PPC_LHAU = 0xac000000,
- PPC_STH = 0xb0000000,
- PPC_STHU = 0xb4000000,
- PPC_LMW = 0xb8000000,
- PPC_STMW = 0xbc000000,
- PPC_LFS = 0xc0000000,
- PPC_LFSU = 0xc4000000,
- PPC_LFD = 0xc8000000,
- PPC_LFDU = 0xcc000000,
- PPC_STFS = 0xd0000000,
- PPC_STFSU = 0xd4000000,
- PPC_STFD = 0xd8000000,
- PPC_STFDU = 0xdc000000,
- PPC_LD = 0xe8000000,
- PPC_LDU = 0xe8000001,
- PPC_LWA = 0xe8000002,
- PPC_FDIVS = 0xec000024,
- PPC_FSUBS = 0xec000028,
- PPC_FADDS = 0xec00002a,
-//------------
- PPC_FSQRTS = 0xec000000,
- PPC_FRES = 0xec000000,
- PPC_FMULS = 0xec000032,
- PPC_FMSUBS = 0xec000000,
- PPC_FMADDS = 0xec000000,
- PPC_FNMSUBS = 0xec000000,
- PPC_FNMADDS = 0xec000000,
- PPC_STD = 0xf8000000,
- PPC_STDU = 0xf8000001,
- PPC_FCMPU = 0xfc000000,
- PPC_FRSP = 0xfc000018,
- PPC_FCTIW = 0xfc000000,
- PPC_FCTIWZ = 0xfc00001e,
- PPC_FDIV = 0xfc000000,
- PPC_FSUB = 0xfc000028,
- PPC_FADD = 0xfc000000,
- PPC_FSQRT = 0xfc000000,
- PPC_FSEL = 0xfc000000,
- PPC_FMUL = 0xfc000000,
- PPC_FRSQRTE = 0xfc000000,
- PPC_FMSUB = 0xfc000000,
- PPC_FMADD = 0xfc000000,
- PPC_FNMSUB = 0xfc000000,
- PPC_FNMADD = 0xfc000000,
- PPC_FCMPO = 0xfc000000,
- PPC_MTFSB1 = 0xfc000000,
- PPC_FNEG = 0xfc000050,
- PPC_MCRFS = 0xfc000000,
- PPC_MTFSB0 = 0xfc000000,
- PPC_FMR = 0xfc000000,
- PPC_MTFSFI = 0xfc000000,
- PPC_FNABS = 0xfc000000,
- PPC_FABS = 0xfc000000,
-//------------
- PPC_MFFS = 0xfc000000,
- PPC_MTFSF = 0xfc000000,
- PPC_FCTID = 0xfc000000,
- PPC_FCTIDZ = 0xfc000000,
- PPC_FCFID = 0xfc000000
-
-} ppcOpcodes_t;
-
-
-// the newly generated code
-static unsigned *buf;
-static int compiledOfs; // in dwords
-static int pass;
-
-// fromt the original bytecode
-static byte *code;
-static int pc;
-
-void AsmCall( void );
-
-double itofConvert[2];
-
-static int Constant4( void ) {
- int v;
-
- v = code[pc] | (code[pc+1]<<8) | (code[pc+2]<<16) | (code[pc+3]<<24);
- pc += 4;
- return v;
-}
-
-static int Constant1( void ) {
- int v;
-
- v = code[pc];
- pc += 1;
- return v;
-}
-
-static void Emit4( char *opname, int i ) {
- #if DEBUG_VM
- if(pass == 1)
- printf("\t\t\t%p %s\t%08lx\n",&buf[compiledOfs],opname,i&0x3ffffff);
- #endif
- buf[ compiledOfs ] = i;
- compiledOfs++;
-}
-
-static void Inst( char *opname, int opcode, int destReg, int aReg, int bReg ) {
- unsigned r;
-
- #if DEBUG_VM
- if(pass == 1)
- printf("\t\t\t%p %s\tr%d,r%d,r%d\n",&buf[compiledOfs],opname,destReg,aReg,bReg);
- #endif
- r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
- buf[ compiledOfs ] = r;
- compiledOfs++;
-}
-
-static void Inst4( char *opname, int opcode, int destReg, int aReg, int bReg, int cReg ) {
- unsigned r;
-
- #if DEBUG_VM
- if(pass == 1)
- printf("\t\t\t%p %s\tr%d,r%d,r%d,r%d\n",&buf[compiledOfs],opname,destReg,aReg,bReg,cReg);
- #endif
- r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) | ( cReg << 6 );
- buf[ compiledOfs ] = r;
- compiledOfs++;
-}
-
-static void InstImm( char *opname, int opcode, int destReg, int aReg, int immediate ) {
- unsigned r;
-
- if ( immediate > 32767 || immediate < -32768 ) {
- Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range, opcode %x,%d,%d", immediate, opcode, destReg, aReg );
- }
- #if DEBUG_VM
- if(pass == 1)
- printf("\t\t\t%p %s\tr%d,r%d,0x%x\n",&buf[compiledOfs],opname,destReg,aReg,immediate);
- #endif
- r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
- buf[ compiledOfs ] = r;
- compiledOfs++;
-}
-
-static void InstImmU( char *opname, int opcode, int destReg, int aReg, int immediate ) {
- unsigned r;
-
- if ( immediate > 0xffff || immediate < 0 ) {
- Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range", immediate );
- }
- #if DEBUG_VM
- if(pass == 1)
- printf("\t\t\t%p %s\tr%d,r%d,0x%x\n",&buf[compiledOfs],opname,destReg,aReg,immediate);
- #endif
- r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
- buf[ compiledOfs ] = r;
- compiledOfs++;
-}
-
-static int pop0, pop1, oc0, oc1;
-static vm_t *tvm;
-static int instruction;
-static byte *jused;
-
-static void spillOpStack(int depth)
-{
- // Store out each register on the operand stack to it's correct location.
- int i;
-
- for(i = 0; i < depth; i++)
- {
- assert(opStackRegType[i]);
- assert(opStackRegType[i] == 1);
- switch(opStackRegType[i])
- {
- case 1: // Integer register
- InstImm( "stw", PPC_STW, opStackIntRegisters[i], R_OPSTACK, i*4+4);
- break;
- case 2: // Float register
- InstImm( "stfs", PPC_STFS, opStackFloatRegisters[i], R_OPSTACK, i*4+4);
- break;
- }
- opStackRegType[i] = 0;
- }
-}
-
-static void loadOpStack(int depth)
-{
- // Back off operand stack pointer and reload all operands.
-// InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -(depth)*4 );
-
- int i;
-
- for(i = 0; i < depth; i++)
- {
- assert(opStackRegType[i] == 0);
- // For now we're stuck reloading everything as an integer.
- opStackLoadInstructionAddr[i] = &buf[compiledOfs];
- InstImm( "lwz", PPC_LWZ, opStackIntRegisters[i], R_OPSTACK, i*4+4);
- opStackRegType[i] = 1;
- }
-}
-
-static void makeFloat(int depth)
-{
- //assert(opStackRegType[depth] == 1);
- if(opStackRegType[depth] == 1)
- {
- unsigned instruction;
- unsigned destReg, aReg, bReg, imm;
-
- if(opStackLoadInstructionAddr[depth])
- {
- // Repatch load instruction to use LFS instead of LWZ
- instruction = *opStackLoadInstructionAddr[depth];
- // Figure out if it's LWZ or LWZX
- if((instruction & 0xfc000000) == PPC_LWZ)
- {
- //printf("patching LWZ at %p to LFS at depth %ld\n",opStackLoadInstructionAddr[depth],depth);
- //printf("old instruction: %08lx\n",instruction);
- // Extract registers
- destReg = (instruction >> 21) & 31;
- aReg = (instruction >> 16) & 31;
- imm = instruction & 0xffff;
-
- // Calculate correct FP register to use.
- // THIS ASSUMES REGISTER USAGE FOR THE STACK IS n, n+1, n+2, etc!
- //printf("old dest: %ld\n",destReg);
- destReg = (destReg - opStackIntRegisters[0]) + opStackFloatRegisters[0];
- instruction = PPC_LFS | ( destReg << 21 ) | ( aReg << 16 ) | imm ;
- //printf("new dest: %ld\n",destReg);
- //printf("new instruction: %08lx\n",instruction);
- }
- else
- {
- //printf("patching LWZX at %p to LFSX at depth %ld\n",opStackLoadInstructionAddr[depth],depth);
- //printf("old instruction: %08lx\n",instruction);
- // Extract registers
- destReg = (instruction >> 21) & 31;
- aReg = (instruction >> 16) & 31;
- bReg = (instruction >> 11) & 31;
- // Calculate correct FP register to use.
- // THIS ASSUMES REGISTER USAGE FOR THE STACK IS n, n+1, n+2, etc!
- //printf("old dest: %ld\n",destReg);
- destReg = (destReg - opStackIntRegisters[0]) + opStackFloatRegisters[0];
- instruction = PPC_LFSX | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
- //printf("new dest: %ld\n",destReg);
- //printf("new instruction: %08lx\n",instruction);
- }
- *opStackLoadInstructionAddr[depth] = instruction;
- opStackLoadInstructionAddr[depth] = 0;
- }
- else
- {
- //printf("doing float constant load at %p for depth %ld\n",&buf[compiledOfs],depth);
- // It was likely loaded as a constant so we have to save/load it. A more
- // interesting implementation might be to generate code to do a "PC relative"
- // load from the VM code region.
- InstImm( "stw", PPC_STW, opStackIntRegisters[depth], R_OPSTACK, depth*4+4);
- // For XXX make sure we force enough NOPs to get the load into
- // another dispatch group to avoid pipeline flush.
- Inst( "ori", PPC_ORI, 0, 0, 0 );
- Inst( "ori", PPC_ORI, 0, 0, 0 );
- Inst( "ori", PPC_ORI, 0, 0, 0 );
- Inst( "ori", PPC_ORI, 0, 0, 0 );
- InstImm( "lfs", PPC_LFS, opStackFloatRegisters[depth], R_OPSTACK, depth*4+4);
- }
- opStackRegType[depth] = 2;
- }
-}
-
-// TJW: Unused
-#if 0
-static void fltop() {
- if (rtopped == qfalse) {
- InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- }
-}
-#endif
-
-#if 0
-static void fltopandsecond() {
- InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 ); // get value from opstack
- InstImm( PPC_LFS, R_SECOND, R_OPSTACK, -4 ); // get value from opstack
- InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
- rtopped = qfalse;
- return;
-}
-#endif
-
-#define assertInteger(depth) assert(opStackRegType[depth] == 1)
-
-/*
-=================
-VM_Compile
-=================
-*/
-void VM_Compile( vm_t *vm, vmHeader_t *header ) {
- int op;
- int maxLength;
- int v;
- int i;
- int opStackDepth;
-
- int mainFunction;
-
- // set up the into-to-float variables
- ((int *)itofConvert)[0] = 0x43300000;
- ((int *)itofConvert)[1] = 0x80000000;
- ((int *)itofConvert)[2] = 0x43300000;
-
- // allocate a very large temp buffer, we will shrink it later
- maxLength = header->codeLength * 8;
- buf = Z_Malloc( maxLength );
- jused = Z_Malloc(header->instructionCount + 2);
- Com_Memset(jused, 0, header->instructionCount+2);
-
- // compile everything twice, so the second pass will have valid instruction
- // pointers for branches
- for ( pass = -1 ; pass < 2 ; pass++ ) {
-
- // translate all instructions
- pc = 0;
- mainFunction = 0;
- opStackDepth = 0;
-
- pop0 = 343545;
- pop1 = 2443545;
- oc0 = -2343535;
- oc1 = 24353454;
- tvm = vm;
- code = (byte *)header + header->codeOffset;
- compiledOfs = 0;
-#ifndef __GNUC__
- // metrowerks seems to require this header in front of functions
- Emit4( (int)(buf+2) );
- Emit4( 0 );
-#endif
-
- for ( instruction = 0 ; instruction < header->instructionCount ; instruction++ ) {
- if ( compiledOfs*4 > maxLength - 16 ) {
- Com_Error( ERR_DROP, "VM_Compile: maxLength exceeded" );
- }
-
- op = code[ pc ];
- if ( !pass ) {
- vm->instructionPointers[ instruction ] = compiledOfs * 4;
- }
- pc++;
- switch ( op ) {
- case 0:
- break;
- case OP_BREAK:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08lx BREAK\n",instruction);
- #endif
- InstImmU( "addi", PPC_ADDI, R_TOP, 0, 0 );
- InstImm( "lwz", PPC_LWZ, R_TOP, R_TOP, 0 ); // *(int *)0 to crash to debugger
- break;
- case OP_ENTER:
- opStackDepth = 0;
- v = Constant4();
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x ENTER\t%04x\n",instruction,v);
- #endif
- opStackRegType[opStackDepth] = 0;
- mainFunction++;
- if(mainFunction == 1)
- {
- // Main VM entry point is the first thing we compile, so save off operand stack
- // registers here. This avoids issues with trying to trick the native compiler
- // into doing it, and properly matches the PowerPC ABI
- InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, -OP_STACK_MAX_DEPTH*4 ); // sub R_STACK, R_STACK, imm
- for(i = 0; i < OP_STACK_MAX_DEPTH; i++)
- InstImm( "stw", PPC_STW, opStackIntRegisters[i], R_REAL_STACK, i*4);
- }
- InstImm( "addi", PPC_ADDI, R_STACK, R_STACK, -v ); // sub R_STACK, R_STACK, imm
- break;
- case OP_CONST:
- v = Constant4();
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x CONST\t%08x\n",instruction,v);
- #endif
- opStackLoadInstructionAddr[opStackDepth] = 0;
- if ( v < 32768 && v >= -32768 ) {
- InstImmU( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], 0, v & 0xffff );
- } else {
- InstImmU( "addis", PPC_ADDIS, opStackIntRegisters[opStackDepth], 0, (v >> 16)&0xffff );
- if ( v & 0xffff ) {
- InstImmU( "ori", PPC_ORI, opStackIntRegisters[opStackDepth], opStackIntRegisters[opStackDepth], v & 0xffff );
- }
- }
- opStackRegType[opStackDepth] = 1;
- opStackDepth += 1;
- if (code[pc] == OP_JUMP) {
- jused[v] = 1;
- }
- break;
- case OP_LOCAL:
- oc1 = Constant4();
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LOCAL\t%08x\n",instruction,oc1);
- #endif
- if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
- oc1 &= vm->dataMask;
- }
- InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], R_STACK, oc1 );
- opStackRegType[opStackDepth] = 1;
- opStackLoadInstructionAddr[opStackDepth] = 0;
- opStackDepth += 1;
- break;
- case OP_ARG:
- v = Constant1();
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x ARG \t%08x\n",instruction,v);
- #endif
- InstImm( "addi", PPC_ADDI, R_EA, R_STACK, v ); // location to put it
- if(opStackRegType[opStackDepth-1] == 1)
- Inst( "stwx", PPC_STWX, opStackIntRegisters[opStackDepth-1], R_EA, R_MEMBASE );
- else
- Inst( "stfsx", PPC_STFSX, opStackFloatRegisters[opStackDepth-1], R_EA, R_MEMBASE );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
-
- break;
- case OP_CALL:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x CALL\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assert(opStackDepth > 0);
- Inst( "mflr", PPC_MFSPR, R_SECOND, 8, 0 ); // move from link register
- InstImm( "stwu", PPC_STWU, R_SECOND, R_REAL_STACK, -16 ); // save off the old return address
-
- // Spill operand stack registers.
- spillOpStack(opStackDepth);
-
- // We need to leave R_OPSTACK pointing to the top entry on the stack, which is the call address.
- // It will be consumed (and R4 decremented) by the AsmCall code.
- InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, opStackDepth*4);
-
- Inst( "mtctr", PPC_MTSPR, R_ASMCALL, 9, 0 ); // move to count register
- Inst( "bctrl", PPC_BCCTR | 1, 20, 0, 0 ); // jump and link to the count register
-
- // R4 now points to the top of the operand stack, which has the return value in it. We want to
- // back off the pointer to point to the base of our local operand stack and then reload the stack.
-
- InstImm("addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -opStackDepth*4);
-
- // Reload operand stack.
- loadOpStack(opStackDepth);
-
- InstImm( "lwz", PPC_LWZ, R_SECOND, R_REAL_STACK, 0 ); // fetch the old return address
- InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, 16 );
- Inst( "mtlr", PPC_MTSPR, R_SECOND, 8, 0 ); // move to link register
- break;
- case OP_PUSH:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x PUSH\n",instruction);
- #endif
- opStackRegType[opStackDepth] = 1; // Garbage int value.
- opStackDepth += 1;
- break;
- case OP_POP:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x POP\n",instruction);
- #endif
- opStackDepth -= 1;
- opStackRegType[opStackDepth] = 0; // ??
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- break;
- case OP_LEAVE:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LEAVE\n",instruction);
- #endif
- assert(opStackDepth == 1);
- assert(opStackRegType[0] != 0);
- // Save return value onto top of op stack. We also have to increment R_OPSTACK
- switch(opStackRegType[0])
- {
- case 1: // Integer register
- InstImm( "stw", PPC_STWU, opStackIntRegisters[0], R_OPSTACK, 4);
- break;
- case 2: // Float register
- InstImm( "stfs", PPC_STFSU, opStackFloatRegisters[0], R_OPSTACK, 4);
- break;
- }
- InstImm( "addi", PPC_ADDI, R_STACK, R_STACK, Constant4() ); // add R_STACK, R_STACK, imm
- if(mainFunction == 1)
- {
- for(i = 0; i < OP_STACK_MAX_DEPTH; i++)
- InstImm( "lwz", PPC_LWZ, opStackIntRegisters[i], R_REAL_STACK, i*4);
- InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, OP_STACK_MAX_DEPTH*4 );
- }
- opStackDepth--;
- opStackRegType[opStackDepth] = 0;
- opStackLoadInstructionAddr[opStackDepth] = 0;
- Inst( "blr", PPC_BCLR, 20, 0, 0 ); // branch unconditionally to link register
- break;
- case OP_LOAD4:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LOAD4\n",instruction);
- #endif
- // We should try to figure out whether to use LWZX or LFSX based
- // on some kind of code analysis after subsequent passes. I think what
- // we could do is store the compiled load instruction address along with
- // the register type. When we hit the first mismatched operator, we go back
- // and patch the load. Since LCC's operand stack should be at 0 depth by the
- // time we hit a branch, this should work fairly well. FIXME FIXME FIXME.
- assertInteger(opStackDepth-1);
- opStackLoadInstructionAddr[opStackDepth-1] = &buf[ compiledOfs ];
- Inst( "lwzx", PPC_LWZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
- opStackRegType[opStackDepth-1] = 1;
- break;
- case OP_LOAD2:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LOAD2\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- Inst( "lhzx", PPC_LHZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
- opStackRegType[opStackDepth-1] = 1;
- break;
- case OP_LOAD1:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LOAD1\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- Inst( "lbzx", PPC_LBZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
- opStackRegType[opStackDepth-1] = 1;
- break;
- case OP_STORE4:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x STORE4\n",instruction);
- #endif
- assertInteger(opStackDepth-2);
- if(opStackRegType[opStackDepth-1] == 1)
- Inst( "stwx", PPC_STWX, opStackIntRegisters[opStackDepth-1],
- opStackIntRegisters[opStackDepth-2], R_MEMBASE ); // store from memory base
- else
- Inst( "stfsx", PPC_STFSX, opStackFloatRegisters[opStackDepth-1],
- opStackIntRegisters[opStackDepth-2], R_MEMBASE ); // store from memory base
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- break;
- case OP_STORE2:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x STORE2\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "sthx", PPC_STHX, opStackIntRegisters[opStackDepth-1],
- opStackIntRegisters[opStackDepth-2], R_MEMBASE ); // store from memory base
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- break;
- case OP_STORE1:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x STORE1\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "stbx", PPC_STBX, opStackIntRegisters[opStackDepth-1],
- opStackIntRegisters[opStackDepth-2], R_MEMBASE ); // store from memory base
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- break;
-
- case OP_EQ:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x EQ\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 4, 2, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (v&0x3ffffff) );
- break;
- case OP_NE:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x NE\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 12, 2, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 4, 2, v );
-
- break;
- case OP_LTI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LTI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 4, 0, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 12, 0, v );
- break;
- case OP_LEI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LEI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 12, 1, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 4, 1, v );
- break;
- case OP_GTI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x GTI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 4, 1, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 12, 1, v );
- break;
- case OP_GEI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x GEI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 12, 0, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 4, 0, v );
- break;
- case OP_LTU:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LTU\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 4, 0, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 12, 0, v );
- break;
- case OP_LEU:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LEU\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 12, 1, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 4, 1, v );
- break;
- case OP_GTU:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x GTU\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 4, 1, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 12, 1, v );
- break;
- case OP_GEU:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x GEU\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 12, 0, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 4, 0, v );
- break;
-
- case OP_EQF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x EQF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 4, 2, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 12, 2, v );
- break;
- case OP_NEF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x NEF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 12, 2, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 4, 2, v );
- break;
- case OP_LTF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LTF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 4, 0, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 12, 0, v );
- break;
- case OP_LEF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LEF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 12, 1, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 4, 1, v );
- break;
- case OP_GTF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x GTF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 4, 1, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 12, 1, v );
- break;
- case OP_GEF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x GEF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- i = Constant4();
- jused[i] = 1;
- InstImm( "bc", PPC_BC, 12, 0, 8 );
- if ( pass==1 ) {
- v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
- } else {
- v = 0;
- }
- Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
-// InstImm( "bc", PPC_BC, 4, 0, v );
- break;
-
- case OP_NEGI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x NEGI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- InstImm( "subfic", PPC_SUBFIC, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- break;
- case OP_ADD:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x ADD\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_SUB:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x SUB\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_DIVI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x DIVI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "divw", PPC_DIVW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_DIVU:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x DIVU\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "divwu", PPC_DIVWU, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_MODI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x MODI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "divw", PPC_DIVW, R_EA, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- Inst( "mullw", PPC_MULLW, R_EA, opStackIntRegisters[opStackDepth-1], R_EA );
- Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], R_EA, opStackIntRegisters[opStackDepth-2] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_MODU:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x MODU\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "divwu", PPC_DIVWU, R_EA, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- Inst( "mullw", PPC_MULLW, R_EA, opStackIntRegisters[opStackDepth-1], R_EA );
- Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], R_EA, opStackIntRegisters[opStackDepth-2] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_MULI:
- case OP_MULU:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x MULI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "mullw", PPC_MULLW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_BAND:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x BAND\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "and", PPC_AND, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_BOR:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x BOR\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "or", PPC_OR, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_BXOR:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x BXOR\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "xor", PPC_XOR, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_BCOM:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x BCOM\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- Inst( "nor", PPC_NOR, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1] );
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- break;
- case OP_LSH:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x LSH\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "slw", PPC_SLW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_RSHI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x RSHI\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "sraw", PPC_SRAW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_RSHU:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x RSHU\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- Inst( "srw", PPC_SRW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
-
- case OP_NEGF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x NEGF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- Inst( "fneg", PPC_FNEG, opStackFloatRegisters[opStackDepth-1], 0, opStackFloatRegisters[opStackDepth-1] );
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- break;
- case OP_ADDF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x ADDF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fadds", PPC_FADDS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_SUBF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x SUBF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fsubs", PPC_FSUBS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_DIVF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x DIVF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst( "fdivs", PPC_FDIVS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- case OP_MULF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x MULF\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
- makeFloat(opStackDepth-2);
- Inst4( "fmuls", PPC_FMULS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], 0, opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
-
- case OP_CVIF:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x CVIF\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- //makeInteger(opStackDepth-1);
- v = (int)&itofConvert;
- InstImmU( "addis", PPC_ADDIS, R_EA, 0, (v >> 16)&0xffff );
- InstImmU( "ori", PPC_ORI, R_EA, R_EA, v & 0xffff );
- InstImmU( "xoris", PPC_XORIS, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0x8000 );
- InstImm( "stw", PPC_STW, opStackIntRegisters[opStackDepth-1], R_EA, 12 );
- InstImm( "lfd", PPC_LFD, opStackFloatRegisters[opStackDepth-1], R_EA, 0 );
- Inst( "ori", PPC_ORI, 0, 0, 0);
- Inst( "ori", PPC_ORI, 0, 0, 0);
- Inst( "ori", PPC_ORI, 0, 0, 0);
- InstImm( "lfd", PPC_LFD, 13, R_EA, 8 );
- Inst( "fsub", PPC_FSUB, opStackFloatRegisters[opStackDepth-1], 13, opStackFloatRegisters[opStackDepth-1] );
- opStackRegType[opStackDepth-1] = 2;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- // Inst( PPC_FRSP, R_TOP, 0, R_TOP );
- break;
- case OP_CVFI:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x CVFI\n",instruction);
- #endif
- makeFloat(opStackDepth-1);
-
- InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, opStackDepth*4);
-
- Inst( "fctiwz", PPC_FCTIWZ, opStackFloatRegisters[opStackDepth-1], 0, opStackFloatRegisters[opStackDepth-1] );
- Inst( "stfiwx", PPC_STFIWX, opStackFloatRegisters[opStackDepth-1], 0, R_OPSTACK ); // save value to opstack (dummy area now)
- Inst( "ori", PPC_ORI, 0, 0, 0);
- Inst( "ori", PPC_ORI, 0, 0, 0);
- Inst( "ori", PPC_ORI, 0, 0, 0);
- Inst( "ori", PPC_ORI, 0, 0, 0);
- InstImm( "lwz", PPC_LWZ, opStackIntRegisters[opStackDepth-1], R_OPSTACK, 0 );
-
- InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -opStackDepth*4);
-
- opStackRegType[opStackDepth-1] = 1;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- break;
- case OP_SEX8:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x SEX8\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- Inst( "extsb", PPC_EXTSB, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- break;
- case OP_SEX16:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x SEX16\n",instruction);
- #endif
- assertInteger(opStackDepth-1);
- Inst( "extsh", PPC_EXTSH, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- break;
-
- case OP_BLOCK_COPY:
- v = Constant4() >> 2;
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x BLOCK_COPY\t%08lx\n",instruction,v<<2);
- #endif
- assert(opStackDepth >= 2);
- assertInteger(opStackDepth-1);
- assertInteger(opStackDepth-2);
- InstImmU( "addi", PPC_ADDI, R_EA, 0, v ); // count
- // FIXME: range check
- Inst( "mtctr", PPC_MTSPR, R_EA, 9, 0 ); // move to count register
-
- Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );
- InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], -4 );
- Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], R_MEMBASE );
- InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], -4 );
-
- InstImm( "lwzu", PPC_LWZU, R_EA, opStackIntRegisters[opStackDepth-1], 4 ); // source
- InstImm( "stwu", PPC_STWU, R_EA, opStackIntRegisters[opStackDepth-2], 4 ); // dest
- Inst( "b", PPC_BC | 0xfff8 , 16, 0, 0 ); // loop
- opStackRegType[opStackDepth-1] = 0;
- opStackRegType[opStackDepth-2] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-2] = 0;
- opStackDepth -= 2;
- break;
-
- case OP_JUMP:
- #if DEBUG_VM
- if(pass == 1)
- printf("%08x JUMP\n",instruction);
- #endif
- assert(opStackDepth == 1);
- assertInteger(opStackDepth-1);
-
- Inst( "rlwinm", PPC_RLWINM | ( 29 << 1 ), opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 2 );
- // FIXME: range check
- Inst( "lwzx", PPC_LWZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_INSTRUCTIONS );
- Inst( "mtctr", PPC_MTSPR, opStackIntRegisters[opStackDepth-1], 9, 0 ); // move to count register
- Inst( "bctr", PPC_BCCTR, 20, 0, 0 ); // jump to the count register
- opStackRegType[opStackDepth-1] = 0;
- opStackLoadInstructionAddr[opStackDepth-1] = 0;
- opStackDepth -= 1;
- break;
- default:
- Com_Error( ERR_DROP, "VM_CompilePPC: bad opcode %i at instruction %i, offset %i", op, instruction, pc );
- }
- pop0 = pop1;
- pop1 = op;
- assert(opStackDepth >= 0);
- assert(opStackDepth < OP_STACK_MAX_DEPTH);
-
- //printf("%4d\t%s\n",opStackDepth,opnames[op]);
- }
-
- Com_Printf( "VM file %s pass %d compiled to %i bytes of code\n", vm->name, (pass+1), compiledOfs*4 );
-
- if ( pass == 0 ) {
- // copy to an exact size buffer on the hunk
- vm->codeLength = compiledOfs * 4;
- vm->codeBase = Hunk_Alloc( vm->codeLength, h_low );
- Com_Memcpy( vm->codeBase, buf, vm->codeLength );
-
- //printf("codeBase: %p\n",vm->codeBase);
-
- Z_Free( buf );
-
- // offset all the instruction pointers for the new location
- for ( i = 0 ; i < header->instructionCount ; i++ ) {
- vm->instructionPointers[i] += (int)vm->codeBase;
- //printf("%08x %08lx\n",i,vm->instructionPointers[i]);
- }
-
- // go back over it in place now to fixup reletive jump targets
- buf = (unsigned *)vm->codeBase;
- } else if ( pass == 1 ) {
- #ifdef MACOS_X
- // On Mac OS X, the following library routine clears the instruction cache for generated code
- MakeDataExecutable(vm->codeBase, vm->codeLength);
- #else
- #warning Need to clear the instruction cache for generated code
- #endif
- }
- }
- if(0)
- {
- char buf[256];
- printf("wait..\n");
- gets(buf);
- }
- Z_Free( jused );
-}
-
-/*
-==============
-VM_CallCompiled
-
-This function is called directly by the generated code
-==============
-*/
-int VM_CallCompiled( vm_t *vm, int *args ) {
- int stack[1024];
- int programStack;
- int stackOnEntry;
- byte *image;
-
- currentVM = vm;
-
- //printf("VM_CallCompiled: %p %08lx %08lx %08lx\n",
- // vm, args[0],args[1],args[2]);
-
- // interpret the code
- vm->currentlyInterpreting = qtrue;
-
- // we might be called recursively, so this might not be the very top
- programStack = vm->programStack;
- stackOnEntry = programStack;
- image = vm->dataBase;
-
- // set up the stack frame
- programStack -= 48;
-
- *(int *)&image[ programStack + 44] = args[9];
- *(int *)&image[ programStack + 40] = args[8];
- *(int *)&image[ programStack + 36] = args[7];
- *(int *)&image[ programStack + 32] = args[6];
- *(int *)&image[ programStack + 28] = args[5];
- *(int *)&image[ programStack + 24] = args[4];
- *(int *)&image[ programStack + 20] = args[3];
- *(int *)&image[ programStack + 16] = args[2];
- *(int *)&image[ programStack + 12] = args[1];
- *(int *)&image[ programStack + 8 ] = args[0];
- *(int *)&image[ programStack + 4 ] = 0; // return stack
- *(int *)&image[ programStack ] = -1; // will terminate the loop on return
-
- // Cheesy... manually save registers used by VM call...
- // off we go into generated code...
- // the PPC calling standard says the parms will all go into R3 - R11, so
- // no special asm code is needed here
-#ifdef __GNUC__
- ((void(*)(int, int, int, int, int, int, int, int))(vm->codeBase))(
- programStack, (int)&stack,
- (int)image, vm->dataMask, (int)&AsmCall,
- (int)vm->instructionPointers, vm->instructionPointersLength,
- (int)vm );
-#else
- ((void(*)(int, int, int, int, int, int, int, int))(vm->codeBase))(
- programStack, (int)&stack,
- (int)image, vm->dataMask, *(int *)&AsmCall /* skip function pointer header */,
- (int)vm->instructionPointers, vm->instructionPointersLength,
- (int)vm );
-#endif
- vm->programStack = stackOnEntry;
-
- vm->currentlyInterpreting = qfalse;
-
- return stack[1];
-}
-
-
-/*
-==================
-AsmCall
-
-Put this at end of file because gcc messes up debug line numbers
-==================
-*/
-#ifdef __GNUC__
-
-void AsmCall( void ) {
-asm (
- // pop off the destination instruction
-" lwz r12,0(r4) \n" // RG_TOP, 0(RG_OPSTACK)
-" addi r4,r4,-4 \n" // RG_OPSTACK, RG_OPSTACK, -4 \n"
-
- // see if it is a system trap
-" cmpwi r12,0 \n" // RG_TOP, 0 \n"
-" bc 12,0, systemTrap \n"
-
- // calling another VM function, so lookup in instructionPointers
-" slwi r12,r12,2 \n" // RG_TOP,RG_TOP,2
- // FIXME: range check
-" lwzx r12, r8, r12 \n" // RG_TOP, RG_INSTRUCTIONS(RG_TOP)
-" mtctr r12 \n" // RG_TOP
-);
-
-#if defined(MACOS_X) && defined(__OPTIMIZE__)
- // On Mac OS X, gcc doesn't push a frame when we are optimized, so trying to tear it down results in grave disorder.
-//#warning Mac OS X optimization on, not popping GCC AsmCall frame
-#else
- // Mac OS X Server and unoptimized compiles include a GCC AsmCall frame
- asm (
-" lwz r1,0(r1) \n" // pop off the GCC AsmCall frame
-" lmw r30,-8(r1) \n"
-);
-#endif
-
-asm (
-" bcctr 20,0 \n" // when it hits a leave, it will branch to the current link register
-
- // calling a system trap
-"systemTrap: \n"
- // convert to positive system call number
-" subfic r12,r12,-1 \n"
-
- // save all our registers, including the current link register
-" mflr r13 \n" // RG_SECOND // copy off our link register
-" addi r1,r1,-92 \n" // required 24 byets of linkage, 32 bytes of parameter, plus our saves
-" stw r3,56(r1) \n" // RG_STACK, -36(REAL_STACK)
-" stw r4,60(r1) \n" // RG_OPSTACK, 4(RG_REAL_STACK)
-" stw r5,64(r1) \n" // RG_MEMBASE, 8(RG_REAL_STACK)
-" stw r6,68(r1) \n" // RG_MEMMASK, 12(RG_REAL_STACK)
-" stw r7,72(r1) \n" // RG_ASMCALL, 16(RG_REAL_STACK)
-" stw r8,76(r1) \n" // RG_INSTRUCTIONS, 20(RG_REAL_STACK)
-" stw r9,80(r1) \n" // RG_NUM_INSTRUCTIONS, 24(RG_REAL_STACK)
-" stw r10,84(r1) \n" // RG_VM, 28(RG_REAL_STACK)
-" stw r13,88(r1) \n" // RG_SECOND, 32(RG_REAL_STACK) // link register
-
- // save the vm stack position to allow recursive VM entry
-" addi r13,r3,-4 \n" // RG_TOP, RG_STACK, -4
-" stw r13,0(r10) \n" //RG_TOP, VM_OFFSET_PROGRAM_STACK(RG_VM)
-
- // save the system call number as the 0th parameter
-" add r3,r3,r5 \n" // r3, RG_STACK, RG_MEMBASE // r3 is the first parameter to vm->systemCalls
-" stwu r12,4(r3) \n" // RG_TOP, 4(r3)
-
- // make the system call with the address of all the VM parms as a parameter
- // vm->systemCalls( &parms )
-" lwz r12,4(r10) \n" // RG_TOP, VM_OFFSET_SYSTEM_CALL(RG_VM)
-" mtctr r12 \n" // RG_TOP
-" bcctrl 20,0 \n"
-" mr r12,r3 \n" // RG_TOP, r3
-
- // pop our saved registers
-" lwz r3,56(r1) \n" // RG_STACK, 0(RG_REAL_STACK)
-" lwz r4,60(r1) \n" // RG_OPSTACK, 4(RG_REAL_STACK)
-" lwz r5,64(r1) \n" // RG_MEMBASE, 8(RG_REAL_STACK)
-" lwz r6,68(r1) \n" // RG_MEMMASK, 12(RG_REAL_STACK)
-" lwz r7,72(r1) \n" // RG_ASMCALL, 16(RG_REAL_STACK)
-" lwz r8,76(r1) \n" // RG_INSTRUCTIONS, 20(RG_REAL_STACK)
-" lwz r9,80(r1) \n" // RG_NUM_INSTRUCTIONS, 24(RG_REAL_STACK)
-" lwz r10,84(r1) \n" // RG_VM, 28(RG_REAL_STACK)
-" lwz r13,88(r1) \n" // RG_SECOND, 32(RG_REAL_STACK)
-" addi r1,r1,92 \n" // RG_REAL_STACK, RG_REAL_STACK, 36
-
- // restore the old link register
-" mtlr r13 \n" // RG_SECOND
-
- // save off the return value
-" stwu r12,4(r4) \n" // RG_TOP, 0(RG_OPSTACK)
-
- // GCC adds its own prolog / epliog code
- );
-}
-#else
-
-// codewarrior version
-
-void asm AsmCall( void ) {
-
- // pop off the destination instruction
-
- lwz r12,0(r4) // RG_TOP, 0(RG_OPSTACK)
-
- addi r4,r4,-4 // RG_OPSTACK, RG_OPSTACK, -4
-
-
-
- // see if it is a system trap
-
- cmpwi r12,0 // RG_TOP, 0
-
- bc 12,0, systemTrap
-
-
-
- // calling another VM function, so lookup in instructionPointers
-
- slwi r12,r12,2 // RG_TOP,RG_TOP,2
-
- // FIXME: range check
-
- lwzx r12, r8, r12 // RG_TOP, RG_INSTRUCTIONS(RG_TOP)
-
- mtctr r12 // RG_TOP
-
-
-
- bcctr 20,0 // when it hits a leave, it will branch to the current link register
-
-
-
- // calling a system trap
-
-systemTrap:
-
- // convert to positive system call number
-
- subfic r12,r12,-1
-
-
-
- // save all our registers, including the current link register
-
- mflr r13 // RG_SECOND // copy off our link register
-
- addi r1,r1,-92 // required 24 byets of linkage, 32 bytes of parameter, plus our saves
-
- stw r3,56(r1) // RG_STACK, -36(REAL_STACK)
-
- stw r4,60(r1) // RG_OPSTACK, 4(RG_REAL_STACK)
-
- stw r5,64(r1) // RG_MEMBASE, 8(RG_REAL_STACK)
-
- stw r6,68(r1) // RG_MEMMASK, 12(RG_REAL_STACK)
-
- stw r7,72(r1) // RG_ASMCALL, 16(RG_REAL_STACK)
-
- stw r8,76(r1) // RG_INSTRUCTIONS, 20(RG_REAL_STACK)
-
- stw r9,80(r1) // RG_NUM_INSTRUCTIONS, 24(RG_REAL_STACK)
-
- stw r10,84(r1) // RG_VM, 28(RG_REAL_STACK)
-
- stw r13,88(r1) // RG_SECOND, 32(RG_REAL_STACK) // link register
-
-
-
- // save the vm stack position to allow recursive VM entry
-
- addi r13,r3,-4 // RG_TOP, RG_STACK, -4
-
- stw r13,0(r10) //RG_TOP, VM_OFFSET_PROGRAM_STACK(RG_VM)
-
-
-
- // save the system call number as the 0th parameter
-
- add r3,r3,r5 // r3, RG_STACK, RG_MEMBASE // r3 is the first parameter to vm->systemCalls
-
- stwu r12,4(r3) // RG_TOP, 4(r3)
-
-
-
- // make the system call with the address of all the VM parms as a parameter
-
- // vm->systemCalls( &parms )
-
- lwz r12,4(r10) // RG_TOP, VM_OFFSET_SYSTEM_CALL(RG_VM)
-
-
-
- // perform macos cross fragment fixup crap
-
- lwz r9,0(r12)
-
- stw r2,52(r1) // save old TOC
-
- lwz r2,4(r12)
-
-
-
- mtctr r9 // RG_TOP
-
- bcctrl 20,0
-
-
-
- lwz r2,52(r1) // restore TOC
-
-
-
- mr r12,r3 // RG_TOP, r3
-
-
-
- // pop our saved registers
-
- lwz r3,56(r1) // RG_STACK, 0(RG_REAL_STACK)
-
- lwz r4,60(r1) // RG_OPSTACK, 4(RG_REAL_STACK)
-
- lwz r5,64(r1) // RG_MEMBASE, 8(RG_REAL_STACK)
-
- lwz r6,68(r1) // RG_MEMMASK, 12(RG_REAL_STACK)
-
- lwz r7,72(r1) // RG_ASMCALL, 16(RG_REAL_STACK)
-
- lwz r8,76(r1) // RG_INSTRUCTIONS, 20(RG_REAL_STACK)
-
- lwz r9,80(r1) // RG_NUM_INSTRUCTIONS, 24(RG_REAL_STACK)
-
- lwz r10,84(r1) // RG_VM, 28(RG_REAL_STACK)
-
- lwz r13,88(r1) // RG_SECOND, 32(RG_REAL_STACK)
-
- addi r1,r1,92 // RG_REAL_STACK, RG_REAL_STACK, 36
-
-
-
- // restore the old link register
-
- mtlr r13 // RG_SECOND
-
-
-
- // save off the return value
-
- stwu r12,4(r4) // RG_TOP, 0(RG_OPSTACK)
-
-
-
- blr
-
-}
-
-
-
-
-#endif
diff --git a/src/qcommon/vm_x86_64.c b/src/qcommon/vm_x86_64.c
index 9fde6e75..e8e827e5 100644
--- a/src/qcommon/vm_x86_64.c
+++ b/src/qcommon/vm_x86_64.c
@@ -43,15 +43,19 @@ static FILE* qdasmout;
static void VM_Destroy_Compiled(vm_t* self);
/*
+
+ |=====================|
+ ^ dataMask ^- programStack rdi
+ |
+ +- r8
eax scratch
ebx scratch
ecx scratch (required for shifts)
edx scratch (required for divisions)
- rsi stack pointer
- rdi program frame pointer
- r8 pointer to begin of real stack memory
- r9 return address to real program
+ rsi stack pointer (opStack)
+ rdi program frame pointer (programStack)
+ r8 pointer data (vm->dataBase)
r10 start of generated code
*/
@@ -266,6 +270,15 @@ static unsigned char op_argsize[256] =
#if 1
#define RANGECHECK(reg) \
emit("andl $0x%x, %%" #reg, vm->dataMask);
+#elif 0
+#define RANGECHECK(reg) \
+ emit("pushl %%" #reg); \
+ emit("andl $0x%x, %%" #reg, ~vm->dataMask); \
+ emit("jz rangecheck_ok_i_%08x", instruction); \
+ emit("int3"); \
+ emit("rangecheck_ok_i_%08x:", instruction); \
+ emit("popl %%" #reg); \
+ emit("andl $0x%x, %%" #reg, vm->dataMask);
#else
#define RANGECHECK(reg)
#endif
@@ -412,10 +425,17 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
Com_Printf("compiling %s\n", vm->name);
+#ifdef DEBUG_VM
+ snprintf(fn_s, sizeof(fn_s), "%.63s.s", vm->name);
+ snprintf(fn_o, sizeof(fn_o), "%.63s.o", vm->name);
+ fd_s = open(fn_s, O_CREAT|O_WRONLY, 0644);
+ fd_o = open(fn_o, O_CREAT|O_WRONLY, 0644);
+#else
snprintf(fn_s, sizeof(fn_s), "/tmp/%.63s.s_XXXXXX", vm->name);
snprintf(fn_o, sizeof(fn_o), "/tmp/%.63s.o_XXXXXX", vm->name);
fd_s = mkstemp(fn_s);
fd_o = mkstemp(fn_o);
+#endif
if(fd_s == -1 || fd_o == -1)
{
if(fd_s != -1) close(fd_s);
@@ -451,8 +471,6 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("or %%r8, %%r8"); // check whether to set up instruction pointers
emit("jnz main");
emit("jmp setupinstructionpointers");
- emit("exit:");
- emit("jmp *%%r9");
emit("main:");
@@ -502,16 +520,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
break;
case OP_LEAVE:
emit("addl $%d, %%edi", iarg); // get rid of stack frame
- RANGECHECK(edi);
- emit("movl 0(%%r8, %%rdi, 1), %%eax"); // get return address
- emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
- emit("cmp $-1, %%eax");
- emit("je jumptoexit%d", instruction);
- emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
- emit("addq %%r10, %%rax");
- emit("jmp *%%rax");
- emit("jumptoexit%d:", instruction);
- emit("jmp exit");
+ emit("ret");
break;
case OP_CALL:
emit("movl 0(%%rsi), %%eax"); // get instr from stack
@@ -522,7 +531,8 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers);
emit("movl (%%rbx, %%rax, 4), %%eax"); // load new relative jump address
emit("addq %%r10, %%rax");
- emit("jmp *%%rax");
+ emit("callq *%%rax");
+ emit("jmp i_%08x", instruction+1);
emit("callSyscall%d:", instruction);
// emit("fnsave 4(%%rsi)");
emit("push %%rsi");
@@ -530,14 +540,19 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("push %%r8");
emit("push %%r9");
emit("push %%r10");
- emit("push %%r10"); // align!
+ emit("movq %%rsp, %%rbx"); // we need to align the stack pointer
+ emit("subq $8, %%rbx"); // |
+ emit("andq $127, %%rbx"); // |
+ emit("subq %%rbx, %%rsp"); // <-+
+ emit("push %%rbx");
emit("negl %%eax"); // convert to actual number
emit("decl %%eax");
// first argument already in rdi
emit("movq %%rax, %%rsi"); // second argument in rsi
emit("movq $%lu, %%rax", (unsigned long)callAsmCall);
emit("callq *%%rax");
- emit("pop %%r10");
+ emit("pop %%rbx");
+ emit("addq %%rbx, %%rsp");
emit("pop %%r10");
emit("pop %%r9");
emit("pop %%r8");
@@ -545,7 +560,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("pop %%rsi");
// emit("frstor 4(%%rsi)");
emit("addq $4, %%rsi");
- emit("movl %%eax, (%%rsi)");
+ emit("movl %%eax, (%%rsi)"); // store return value
break;
case OP_PUSH:
emit("addq $4, %%rsi");
@@ -634,21 +649,21 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
XJ("jb");
break;
case OP_LOAD1:
- emit("movl 0(%%rsi), %%eax"); // get pointer from stack
+ emit("movl 0(%%rsi), %%eax"); // get value from stack
RANGECHECK(eax);
emit("movb 0(%%r8, %%rax, 1), %%al"); // deref into eax
emit("andq $255, %%rax");
emit("movl %%eax, 0(%%rsi)"); // store on stack
break;
case OP_LOAD2:
- emit("movl 0(%%rsi), %%eax"); // get pointer from stack
+ emit("movl 0(%%rsi), %%eax"); // get value from stack
RANGECHECK(eax);
- emit("movw 0(%%r8, %%rax, 1), %%rax"); // deref into eax
+ emit("movw 0(%%r8, %%rax, 1), %%ax"); // deref into eax
emit("movl %%eax, 0(%%rsi)"); // store on stack
break;
case OP_LOAD4:
- emit("movl 0(%%rsi), %%eax"); // get pointer from stack
- RANGECHECK(eax);
+ emit("movl 0(%%rsi), %%eax"); // get value from stack
+ RANGECHECK(eax); // not a pointer!?
emit("movl 0(%%r8, %%rax, 1), %%eax"); // deref into eax
emit("movl %%eax, 0(%%rsi)"); // store on stack
break;
@@ -664,7 +679,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
RANGECHECK(ebx);
- emit("movw %%rax, 0(%%r8, %%rbx, 1)"); // store in memory
+ emit("movw %%ax, 0(%%r8, %%rbx, 1)"); // store in memory
emit("subq $8, %%rsi");
break;
case OP_STORE4:
@@ -703,14 +718,14 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
break;
case OP_SEX8:
- emit("movw 0(%%rsi), %%rax");
+ emit("movw 0(%%rsi), %%ax");
emit("andq $255, %%rax");
emit("cbw");
emit("cwde");
emit("movl %%eax, 0(%%rsi)");
break;
case OP_SEX16:
- emit("movw 0(%%rsi), %%rax");
+ emit("movw 0(%%rsi), %%ax");
emit("cwde");
emit("movl %%eax, 0(%%rsi)");
break;
@@ -741,14 +756,15 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("xorl %%edx, %%edx");
- emit("divl 4(%%rsi)");
+ emit("cdq");
+ emit("idivl 4(%%rsi)");
emit("movl %%edx, 0(%%rsi)");
break;
case OP_MODU:
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("xorl %%edx, %%edx");
- emit("idivl 4(%%rsi)");
+ emit("divl 4(%%rsi)");
emit("movl %%edx, 0(%%rsi)");
break;
case OP_MULI:
@@ -847,7 +863,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
{
emit("movl $i_%08x-start, %d(%%rax)", instruction, instruction*4);
}
- emit("jmp exit");
+ emit("ret");
emit("debugger:");
if(1);
@@ -883,28 +899,30 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
// call code with r8 set to zero to set up instruction pointers
__asm__ __volatile__ (
" xorq %%r8,%%r8 \r\n" \
- " movq $doneinit,%%r9 \r\n" \
" movq %0,%%r10 \r\n" \
- " jmp *%%r10 \r\n" \
- "doneinit: \r\n" \
+ " callq *%%r10 \r\n" \
:
: "m" (entryPoint)
- : "%r8", "%r9", "%r10", "%rax"
+ : "%r8", "%r10", "%rax"
);
#ifdef DEBUG_VM
fflush(qdasmout);
+ fclose(qdasmout);
#endif
Com_Printf( "VM file %s compiled to %i bytes of code (%p - %p)\n", vm->name, vm->codeLength, vm->codeBase, vm->codeBase+vm->codeLength );
out:
close(fd_o);
+
+#ifndef DEBUG_VM
if(!com_developer->integer)
{
unlink(fn_o);
unlink(fn_s);
}
+#endif
}
@@ -978,16 +996,16 @@ int VM_CallCompiled( vm_t *vm, int *args ) {
__asm__ __volatile__ (
" movq %5,%%rsi \r\n" \
" movl %4,%%edi \r\n" \
- " movq $done,%%r9 \r\n" \
" movq %2,%%r10 \r\n" \
" movq %3,%%r8 \r\n" \
- " jmp *%%r10 \r\n" \
- "done: \r\n" \
+ " subq $24, %%rsp # fix alignment as call pushes one value \r\n" \
+ " callq *%%r10 \r\n" \
+ " addq $24, %%rsp \r\n" \
" movl %%edi, %0 \r\n" \
" movq %%rsi, %1 \r\n" \
: "=m" (programStack), "=m" (opStack)
: "m" (entryPoint), "m" (vm->dataBase), "m" (programStack), "m" (opStack)
- : "%rsi", "%rdi", "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r15", "%xmm0"
+ : "%rsi", "%rdi", "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r10", "%r15", "%xmm0"
);
if ( opStack != &stack[1] ) {