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

📄 vm_ppc_new.c

📁 quakeIII源码这个不用我多说吧
💻 C
📖 第 1 页 / 共 5 页
字号:
		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;
	}
    }
    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_STAC

⌨️ 快捷键说明

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