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

📄 vm_ppc.c

📁 quakeIII源码这个不用我多说吧
💻 C
📖 第 1 页 / 共 4 页
字号:
	if ( immediate > 0xffff || immediate < 0 ) {
		Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range", immediate );
	}
    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 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;
	}
	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
#if 0
static void fltop() {
    if (rtopped == qfalse) {
	InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );		// get value from opstack
    }
}
#endif

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;
}

/*
=================
VM_Compile
=================
*/
void VM_Compile( vm_t *vm, vmHeader_t *header ) {
	int		op;
	int		maxLength;
	int		v;
	int		i;
        
	// 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++ ) {

	rtopped = qfalse;
        // translate all instructions
        pc = 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:
                InstImmU( PPC_ADDI, R_TOP, 0, 0 );
                InstImm( PPC_LWZ, R_TOP, R_TOP, 0 );			// *(int *)0 to crash to debugger
		rtopped = qfalse;
                break;
            case OP_ENTER:
                InstImm( PPC_ADDI, R_STACK, R_STACK, -Constant4() );	// sub R_STACK, R_STACK, imm
		rtopped = qfalse;
                break;
            case OP_CONST:
                v = Constant4();
		if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
		    v &= vm->dataMask;
		}
                if ( v < 32768 && v >= -32768 ) {
                    InstImmU( PPC_ADDI, R_TOP, 0, v & 0xffff );
                } else {
                    InstImmU( PPC_ADDIS, R_TOP, 0, (v >> 16)&0xffff );
                    if ( v & 0xffff ) {
                        InstImmU( PPC_ORI, R_TOP, R_TOP, 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;
		}
		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 (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;
                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;
                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;
                break;
            case OP_PUSH:
                InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, 4 );
		rtopped = qfalse;
                break;
            case OP_POP:
                InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
		rtopped = qfalse;
                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;
                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;
                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;
                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;
                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;
                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;
                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;
                break;

            case OP_EQ:
                ltopandsecond();					// get value from opstack
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
                i = Constant4();
				jused[i] = 1;
                InstImm( 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;
                break;
            case OP_NE:
                ltopandsecond();					// get value from opstack
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
                i = Constant4();
				jused[i] = 1;
                InstImm( 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;
                break;
            case OP_LTI:
                ltopandsecond();					// get value from opstack
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
                i = Constant4();
				jused[i] = 1;
                InstImm( 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;
                break;
            case OP_LEI:
                ltopandsecond();					// get value from opstack
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
                i = Constant4();
				jused[i] = 1;
                InstImm( 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;
                break;
            case OP_GTI:

⌨️ 快捷键说明

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