aboutsummaryrefslogtreecommitdiffstats
path: root/code
diff options
context:
space:
mode:
Diffstat (limited to 'code')
-rw-r--r--code/qcommon/qfiles.h6
-rw-r--r--code/qcommon/vm.c90
-rw-r--r--code/qcommon/vm_local.h3
-rw-r--r--code/qcommon/vm_x86.c6
-rw-r--r--code/tools/asm/q3asm.c8
5 files changed, 93 insertions, 20 deletions
diff --git a/code/qcommon/qfiles.h b/code/qcommon/qfiles.h
index 3fd44ed..1aab668 100644
--- a/code/qcommon/qfiles.h
+++ b/code/qcommon/qfiles.h
@@ -43,7 +43,8 @@ QVM files
========================================================================
*/
-#define VM_MAGIC 0x12721444
+#define VM_MAGIC 0x12721444
+#define VM_MAGIC_VER2 0x12721445
typedef struct {
int vmMagic;
@@ -56,6 +57,9 @@ typedef struct {
int dataLength;
int litLength; // ( dataLength - litLength ) should be byteswapped on load
int bssLength; // zero filled memory appended to datalength
+
+ //!!! below here is VM_MAGIC_VER2 !!!
+ int jtrgLength; // number of jump table targets
} vmHeader_t;
diff --git a/code/qcommon/vm.c b/code/qcommon/vm.c
index 080599d..c5f2c75 100644
--- a/code/qcommon/vm.c
+++ b/code/qcommon/vm.c
@@ -381,7 +381,7 @@ vm_t *VM_Restart( vm_t *vm ) {
// load the image
Com_Printf( "VM_Restart()\n", filename );
Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name );
- Com_Printf( "Loading vm file %s.\n", filename );
+ Com_Printf( "Loading vm file %s...\n", filename );
length = FS_ReadFile( filename, (void **)&header );
if ( !header ) {
Com_Error( ERR_DROP, "VM_Restart failed.\n" );
@@ -392,14 +392,28 @@ vm_t *VM_Restart( vm_t *vm ) {
((int *)header)[i] = LittleLong( ((int *)header)[i] );
}
- // validate
- if ( header->vmMagic != VM_MAGIC
- || header->bssLength < 0
- || header->dataLength < 0
- || header->litLength < 0
- || header->codeLength <= 0 ) {
- VM_Free( vm );
- Com_Error( ERR_FATAL, "%s has bad header", filename );
+ if( header->vmMagic == VM_MAGIC_VER2 ) {
+ Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" );
+ // validate
+ if ( header->vmMagic != VM_MAGIC_VER2
+ || header->jtrgLength < 0
+ || header->bssLength < 0
+ || header->dataLength < 0
+ || header->litLength < 0
+ || header->codeLength <= 0 ) {
+ VM_Free( vm );
+ Com_Error( ERR_FATAL, "%s has bad header", filename );
+ }
+ } else {
+ // validate
+ if ( header->vmMagic != VM_MAGIC
+ || header->bssLength < 0
+ || header->dataLength < 0
+ || header->litLength < 0
+ || header->codeLength <= 0 ) {
+ VM_Free( vm );
+ Com_Error( ERR_FATAL, "%s has bad header", filename );
+ }
}
// round up to next power of 2 so all data operations can
@@ -420,6 +434,19 @@ vm_t *VM_Restart( vm_t *vm ) {
*(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) );
}
+ if( header->vmMagic == VM_MAGIC_VER2 ) {
+ vm->numJumpTableTargets = header->jtrgLength >> 2;
+ Com_Printf( "Loading %d jump table targets\n", vm->numJumpTableTargets );
+ Com_Memset( vm->jumpTableTargets, 0, header->jtrgLength );
+ Com_Memcpy( vm->jumpTableTargets, (byte *)header + header->dataOffset +
+ header->dataLength + header->litLength, header->jtrgLength );
+
+ // byte swap the longs
+ for ( i = 0 ; i < header->jtrgLength ; i += 4 ) {
+ *(int *)(vm->jumpTableTargets + i) = LittleLong( *(int *)(vm->jumpTableTargets + i ) );
+ }
+ }
+
// free the original file
FS_FreeFile( header );
@@ -504,7 +531,7 @@ vm_t *VM_Create( const char *module, long (*systemCalls)(long *),
// load the image
Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name );
- Com_Printf( "Loading vm file %s.\n", filename );
+ Com_Printf( "Loading vm file %s...\n", filename );
length = FS_ReadFile( filename, (void **)&header );
if ( !header ) {
Com_Printf( "Failed.\n" );
@@ -517,14 +544,28 @@ vm_t *VM_Create( const char *module, long (*systemCalls)(long *),
((int *)header)[i] = LittleLong( ((int *)header)[i] );
}
- // validate
- if ( header->vmMagic != VM_MAGIC
- || header->bssLength < 0
- || header->dataLength < 0
- || header->litLength < 0
- || header->codeLength <= 0 ) {
- VM_Free( vm );
- Com_Error( ERR_FATAL, "%s has bad header", filename );
+ if( header->vmMagic == VM_MAGIC_VER2 ) {
+ Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" );
+ // validate
+ if ( header->vmMagic != VM_MAGIC_VER2
+ || header->jtrgLength < 0
+ || header->bssLength < 0
+ || header->dataLength < 0
+ || header->litLength < 0
+ || header->codeLength <= 0 ) {
+ VM_Free( vm );
+ Com_Error( ERR_FATAL, "%s has bad header", filename );
+ }
+ } else {
+ // validate
+ if ( header->vmMagic != VM_MAGIC
+ || header->bssLength < 0
+ || header->dataLength < 0
+ || header->litLength < 0
+ || header->codeLength <= 0 ) {
+ VM_Free( vm );
+ Com_Error( ERR_FATAL, "%s has bad header", filename );
+ }
}
// round up to next power of 2 so all data operations can
@@ -546,6 +587,19 @@ vm_t *VM_Create( const char *module, long (*systemCalls)(long *),
*(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) );
}
+ if( header->vmMagic == VM_MAGIC_VER2 ) {
+ vm->numJumpTableTargets = header->jtrgLength >> 2;
+ Com_Printf( "Loading %d jump table targets\n", vm->numJumpTableTargets );
+ vm->jumpTableTargets = Hunk_Alloc( header->jtrgLength, h_high );
+ Com_Memcpy( vm->jumpTableTargets, (byte *)header + header->dataOffset +
+ header->dataLength + header->litLength, header->jtrgLength );
+
+ // byte swap the longs
+ for ( i = 0 ; i < header->jtrgLength ; i += 4 ) {
+ *(int *)(vm->jumpTableTargets + i) = LittleLong( *(int *)(vm->jumpTableTargets + i ) );
+ }
+ }
+
// allocate space for the jump targets, which will be filled in by the compile/prep functions
vm->instructionPointersLength = header->instructionCount * 4;
vm->instructionPointers = Hunk_Alloc( vm->instructionPointersLength, h_high );
diff --git a/code/qcommon/vm_local.h b/code/qcommon/vm_local.h
index f6fc043..eb58fff 100644
--- a/code/qcommon/vm_local.h
+++ b/code/qcommon/vm_local.h
@@ -161,6 +161,9 @@ struct vm_s {
// fqpath member added 7/20/02 by T.Ray
char fqpath[MAX_QPATH+1] ;
+
+ byte *jumpTableTargets;
+ int numJumpTableTargets;
};
diff --git a/code/qcommon/vm_x86.c b/code/qcommon/vm_x86.c
index a46161a..63b3e1b 100644
--- a/code/qcommon/vm_x86.c
+++ b/code/qcommon/vm_x86.c
@@ -419,6 +419,12 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
Com_Memset(jused, 0, header->instructionCount+2);
+ // ensure that the optimisation pass knows about all the jump
+ // table targets
+ for( i = 0; i < vm->numJumpTableTargets; i++ ) {
+ jused[ *(int *)(vm->jumpTableTargets + ( i * sizeof( int ) ) ) ] = 1;
+ }
+
for(pass=0;pass<2;pass++) {
oc0 = -23423;
oc1 = -234354;
diff --git a/code/tools/asm/q3asm.c b/code/tools/asm/q3asm.c
index 6c529ab..7d88e73 100644
--- a/code/tools/asm/q3asm.c
+++ b/code/tools/asm/q3asm.c
@@ -135,6 +135,7 @@ typedef enum {
DATASEG, // initialized 32 bit data, will be byte swapped
LITSEG, // strings
BSSSEG, // 0 filled
+ JTRGSEG, // psuedo-segment that contains only jump table targets
NUM_SEGMENTS
} segmentName_t;
@@ -989,6 +990,8 @@ STAT("ADDRESS");
/* Addresses are 32 bits wide, and therefore go into data segment. */
HackToSegment( DATASEG );
EmitInt( currentSegment, v );
+ if( passNumber == 1 && token[ 0 ] == '$' ) // crude test for labels
+ EmitInt( &segment[ JTRGSEG ], v );
return 1;
}
return 0;
@@ -1375,7 +1378,7 @@ void WriteVmFile( void ) {
return;
}
- header.vmMagic = VM_MAGIC;
+ header.vmMagic = VM_MAGIC_VER2;
header.instructionCount = instructionCount;
header.codeOffset = sizeof( header );
header.codeLength = segment[CODESEG].imageUsed;
@@ -1383,6 +1386,7 @@ void WriteVmFile( void ) {
header.dataLength = segment[DATASEG].imageUsed;
header.litLength = segment[LITSEG].imageUsed;
header.bssLength = segment[BSSSEG].imageUsed;
+ header.jtrgLength = segment[JTRGSEG].imageUsed;
report( "Writing to %s\n", imageName );
@@ -1392,6 +1396,7 @@ void WriteVmFile( void ) {
SafeWrite( f, &segment[CODESEG].image, segment[CODESEG].imageUsed );
SafeWrite( f, &segment[DATASEG].image, segment[DATASEG].imageUsed );
SafeWrite( f, &segment[LITSEG].image, segment[LITSEG].imageUsed );
+ SafeWrite( f, &segment[JTRGSEG].image, segment[JTRGSEG].imageUsed );
fclose( f );
}
@@ -1417,6 +1422,7 @@ void Assemble( void ) {
for ( passNumber = 0 ; passNumber < 2 ; passNumber++ ) {
segment[LITSEG].segmentBase = segment[DATASEG].imageUsed;
segment[BSSSEG].segmentBase = segment[LITSEG].segmentBase + segment[LITSEG].imageUsed;
+ segment[JTRGSEG].segmentBase = segment[BSSSEG].segmentBase + segment[BSSSEG].imageUsed;
for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) {
segment[i].imageUsed = 0;
}