⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vm_ppc.c

📁 quakeIII源码这个不用我多说吧
💻 C
📖 第 1 页 / 共 4 页
字号:
                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;
                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 );
		// 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;
                break;
            default:
                Com_Error( ERR_DROP, "VM_CompilePPC: bad opcode %i at instruction %i, offset %i", op, instruction, pc );
            }
	    pop0 = pop1;
	    pop1 = 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 );
	    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;
	    }

	    // go back over it in place now to fixup reletive jump targets
	    buf = (unsigned *)vm->codeBase;
	}
    }
    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;

	// 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

	// 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 / epilog 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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -