r156 - in trunk/code: qcommon tools/asm

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Thu Oct 13 10:47:00 EDT 2005


Author: tma
Date: 2005-10-13 10:47:00 -0400 (Thu, 13 Oct 2005)
New Revision: 156

Modified:
   trunk/code/qcommon/qfiles.h
   trunk/code/qcommon/vm.c
   trunk/code/qcommon/vm_local.h
   trunk/code/qcommon/vm_x86.c
   trunk/code/tools/asm/q3asm.c
Log:
* (Non-trivial) fix to the "opStack corrupted in compiled code" bug


Modified: trunk/code/qcommon/qfiles.h
===================================================================
--- trunk/code/qcommon/qfiles.h	2005-10-13 01:55:31 UTC (rev 155)
+++ trunk/code/qcommon/qfiles.h	2005-10-13 14:47:00 UTC (rev 156)
@@ -43,7 +43,8 @@
 ========================================================================
 */
 
-#define	VM_MAGIC	0x12721444
+#define	VM_MAGIC			0x12721444
+#define	VM_MAGIC_VER2	0x12721445
 typedef struct {
 	int		vmMagic;
 
@@ -56,6 +57,9 @@
 	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;
 
 

Modified: trunk/code/qcommon/vm.c
===================================================================
--- trunk/code/qcommon/vm.c	2005-10-13 01:55:31 UTC (rev 155)
+++ trunk/code/qcommon/vm.c	2005-10-13 14:47:00 UTC (rev 156)
@@ -381,7 +381,7 @@
 	// 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 @@
 		((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 @@
 		*(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 @@
 
 	// 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 @@
 		((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 @@
 		*(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 );

Modified: trunk/code/qcommon/vm_local.h
===================================================================
--- trunk/code/qcommon/vm_local.h	2005-10-13 01:55:31 UTC (rev 155)
+++ trunk/code/qcommon/vm_local.h	2005-10-13 14:47:00 UTC (rev 156)
@@ -161,6 +161,9 @@
 
 // fqpath member added 7/20/02 by T.Ray
 	char		fqpath[MAX_QPATH+1] ;
+
+	byte		*jumpTableTargets;
+	int			numJumpTableTargets;
 };
 
 

Modified: trunk/code/qcommon/vm_x86.c
===================================================================
--- trunk/code/qcommon/vm_x86.c	2005-10-13 01:55:31 UTC (rev 155)
+++ trunk/code/qcommon/vm_x86.c	2005-10-13 14:47:00 UTC (rev 156)
@@ -419,6 +419,12 @@
 	
 	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;

Modified: trunk/code/tools/asm/q3asm.c
===================================================================
--- trunk/code/tools/asm/q3asm.c	2005-10-13 01:55:31 UTC (rev 155)
+++ trunk/code/tools/asm/q3asm.c	2005-10-13 14:47:00 UTC (rev 156)
@@ -135,6 +135,7 @@
 	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 @@
 /* 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 @@
 		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 @@
 	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 @@
 	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 @@
 	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;
 		}




More information about the quake3-commits mailing list