コード例 #1
0
void JitArm::stmw(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITLoadStoreOff);
	FALLBACK_IF(!Core::g_CoreStartupParameter.bFastmem);

	u32 a = inst.RA;
	ARMReg rA = gpr.GetReg();
	ARMReg rB = gpr.GetReg();
	ARMReg rC = gpr.GetReg();
	MOVI2R(rA, inst.SIMM_16);
	if (a)
		ADD(rA, rA, gpr.R(a));
	Operand2 mask(2, 1); // ~(Memory::MEMVIEW32_MASK)
	BIC(rA, rA, mask); // 3
	MOVI2R(rB, (u32)Memory::base, false); // 4-5
	ADD(rA, rA, rB); // 6

	for (int i = inst.RD; i < 32; i++)
	{
		ARMReg RX = gpr.R(i);
		REV(rC, RX);
		STR(rC, rA, (i - inst.RD) * 4);
	}
	gpr.Unlock(rA, rB, rC);
}
コード例 #2
0
void JitArm::lha(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(LoadStore)

	ARMReg rA = gpr.GetReg();
	ARMReg rB = gpr.GetReg();
	ARMReg RD = gpr.R(inst.RD);
	LDR(rA, R9, PPCSTATE_OFF(Exceptions));
	CMP(rA, EXCEPTION_DSI);
	FixupBranch DoNotLoad = B_CC(CC_EQ);

	if (inst.RA)
	{
		MOVI2R(rB, inst.SIMM_16);
		ARMReg RA = gpr.R(inst.RA);
		ADD(rB, rB, RA);
	}
	else	
		MOVI2R(rB, (u32)inst.SIMM_16);
	
	MOVI2R(rA, (u32)&Memory::Read_U16);	
	PUSH(4, R0, R1, R2, R3);
	MOV(R0, rB);
	BL(rA);
	MOV(rA, R0);
	SXTH(rA, rA);
	POP(4, R0, R1, R2, R3);
	MOV(RD, rA);
	gpr.Unlock(rA, rB);
	SetJumpTarget(DoNotLoad);
}
コード例 #3
0
void JitArm::stbu(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(LoadStore)
	ARMReg RA = gpr.R(inst.RA);
	ARMReg RS = gpr.R(inst.RS);
	ARMReg ValueReg = gpr.GetReg();
	ARMReg Addr = gpr.GetReg();
	ARMReg Function = gpr.GetReg();
	
	MOVI2R(Addr, inst.SIMM_16);
	ADD(Addr, Addr, RA);

	// Check for DSI exception prior to writing back address
	LDR(Function, R9, PPCSTATE_OFF(Exceptions));
	CMP(Function, EXCEPTION_DSI);
	FixupBranch DoNotWrite = B_CC(CC_EQ);
	MOV(RA, Addr);
	SetJumpTarget(DoNotWrite);

	MOV(ValueReg, RS);
	
	MOVI2R(Function, (u32)&Memory::Write_U8);	
	PUSH(4, R0, R1, R2, R3);
	MOV(R0, ValueReg);
	MOV(R1, Addr);
	BL(Function);
	POP(4, R0, R1, R2, R3);

	gpr.Unlock(ValueReg, Addr, Function);
}
コード例 #4
0
void JitArm::sth(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(LoadStore)

	ARMReg RS = gpr.R(inst.RS);
	ARMReg ValueReg = gpr.GetReg();
	ARMReg Addr = gpr.GetReg();
	ARMReg Function = gpr.GetReg();

	MOV(ValueReg, RS);
	if (inst.RA)
	{
		MOVI2R(Addr, inst.SIMM_16);
		ARMReg RA = gpr.R(inst.RA);
		ADD(Addr, Addr, RA);
	}
	else
		MOVI2R(Addr, (u32)inst.SIMM_16);
	
	MOVI2R(Function, (u32)&Memory::Write_U16);	
	PUSH(4, R0, R1, R2, R3);
	MOV(R0, ValueReg);
	MOV(R1, Addr);
	BL(Function);
	POP(4, R0, R1, R2, R3);
	gpr.Unlock(ValueReg, Addr, Function);
}
コード例 #5
0
void JitArm::stfs(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITLoadStoreFloatingOff);

	ARMReg rA = gpr.GetReg();
	ARMReg rB = gpr.GetReg();
	ARMReg v0 = fpr.R0(inst.FS);
	VCVT(S0, v0, 0);

	if (inst.RA)
	{
		MOVI2R(rB, inst.SIMM_16);
		ARMReg RA = gpr.R(inst.RA);
		ADD(rB, rB, RA);
	}
	else
	{
		MOVI2R(rB, (u32)inst.SIMM_16);
	}

	MOVI2R(rA, (u32)&Memory::Write_U32);
	PUSH(4, R0, R1, R2, R3);
	VMOV(R0, S0);
	MOV(R1, rB);

	BL(rA);

	POP(4, R0, R1, R2, R3);

	gpr.Unlock(rA, rB);
}
コード例 #6
0
void JitArm::lwz(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(LoadStore)

	ARMReg rA = gpr.GetReg();
	ARMReg rB = gpr.GetReg();
	ARMReg RD = gpr.R(inst.RD);
	LDR(rA, R9, PPCSTATE_OFF(Exceptions));
	CMP(rA, EXCEPTION_DSI);
	FixupBranch DoNotLoad = B_CC(CC_EQ);
	{
		if (inst.RA)
		{
			MOVI2R(rB, inst.SIMM_16);
			ARMReg RA = gpr.R(inst.RA);
			ADD(rB, rB, RA);
		}
		else
			MOVI2R(rB, (u32)inst.SIMM_16);

		MOVI2R(rA, (u32)&Memory::Read_U32);	
		PUSH(4, R0, R1, R2, R3);
		MOV(R0, rB);
		BL(rA);
		MOV(rA, R0);
		POP(4, R0, R1, R2, R3);
		MOV(RD, rA);
		gpr.Unlock(rA, rB);
	}
	SetJumpTarget(DoNotLoad);
	if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
		(inst.hex & 0xFFFF0000) == 0x800D0000 &&
		(Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
		(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
		Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
	{
		gpr.Flush();
		fpr.Flush();
		
		// if it's still 0, we can wait until the next event
		TST(RD, RD);
		FixupBranch noIdle = B_CC(CC_NEQ);
		rA = gpr.GetReg();	
		
		MOVI2R(rA, (u32)&PowerPC::OnIdle);
		MOVI2R(R0, PowerPC::ppcState.gpr[inst.RA] + (s32)(s16)inst.SIMM_16); 
		BL(rA);

		gpr.Unlock(rA);
		WriteExceptionExit();

		SetJumpTarget(noIdle);

		//js.compilerPC += 8;
		return;
	}
}
コード例 #7
0
void JitArm::SafeLoadToReg(bool fastmem, u32 dest, s32 addr, s32 offsetReg, int accessSize, s32 offset, bool signExtend, bool reverse)
{
    ARMReg RD = gpr.R(dest);
    if (Core::g_CoreStartupParameter.bFastmem && fastmem)
    {
        if (addr != -1)
            MOV(R10, gpr.R(addr));
        else
            MOV(R10, 0);

        UnsafeLoadToReg(RD, R10, accessSize, offset);
        return;
    }
    ARMReg rA = gpr.GetReg();
    ARMReg rB = gpr.GetReg();

    if (offsetReg == -1)
        MOVI2R(rA, offset);
    else
        MOV(rA, gpr.R(offsetReg));

    if (addr != -1)
        ADD(rA, rA, gpr.R(addr));

    switch (accessSize)
    {
    case 8:
        MOVI2R(rB, (u32)&Memory::Read_U8);
        break;
    case 16:
        MOVI2R(rB, (u32)&Memory::Read_U16);
        break;
    case 32:
        MOVI2R(rB, (u32)&Memory::Read_U32);
        break;
    }
    PUSH(4, R0, R1, R2, R3);
    MOV(R0, rA);
    BL(rB);
    MOV(rA, R0);
    POP(4, R0, R1, R2, R3);
    MOV(RD, rA);
    if (signExtend) // Only on 16 loads
        SXTH(RD, RD);
    if (reverse)
    {
        if (accessSize == 32)
            REV(RD, RD);
        else if (accessSize == 16)
            REV16(RD, RD);
    }
    gpr.Unlock(rA, rB);
}
コード例 #8
0
void JitArm::UnsafeLoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offsetReg, s32 offset)
{
	ARMReg rA = gpr.GetReg();
	if (offsetReg == -1)
	{
		MOVI2R(rA, offset, false); // -3
		ADD(addr, addr, rA); // - 1
	}
	else
	{
		NOP(2); // -3, -2
		// offsetReg is preloaded here
		ADD(addr, addr, gpr.R(offsetReg)); // -1
	}

	// All this gets replaced on backpatch
	Operand2 mask(2, 1); // ~(Memory::MEMVIEW32_MASK)
	BIC(addr, addr, mask); // 1
	MOVI2R(rA, (u32)Memory::base, false); // 2-3
	ADD(addr, addr, rA); // 4
	switch (accessSize)
	{
		case 32:
			LDR(dest, addr); // 5
		break;
		case 16:
			LDRH(dest, addr);
		break;
		case 8:
			LDRB(dest, addr);
		break;
	}
	switch (accessSize)
	{
		case 32:
			REV(dest, dest); // 6
		break;
		case 16:
			REV16(dest, dest);
		break;
		case 8:
			NOP(1);
		break;

	}
	NOP(2); // 7-8
	gpr.Unlock(rA);
}
コード例 #9
0
ファイル: JitArm_Paired.cpp プロジェクト: Catnips/dolphin
void JitArm::ps_rsqrte(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITPairedOff);
	FALLBACK_IF(inst.Rc);

	u32 b = inst.FB, d = inst.FD;

	ARMReg vB0 = fpr.R0(b);
	ARMReg vB1 = fpr.R1(b);
	ARMReg vD0 = fpr.R0(d, false);
	ARMReg vD1 = fpr.R1(d, false);
	ARMReg fpscrReg = gpr.GetReg();
	ARMReg V0 = D1;
	ARMReg rA = gpr.GetReg();

	MOVI2R(fpscrReg, (u32)&PPC_NAN);
	VLDR(V0, fpscrReg, 0);
	LDR(fpscrReg, R9, PPCSTATE_OFF(fpscr));

	VCMP(vB0);
	VMRS(_PC);
	FixupBranch Less0 = B_CC(CC_LT);
		VMOV(vD0, V0);
		SetFPException(fpscrReg, FPSCR_VXSQRT);
		FixupBranch SkipOrr0 = B();
	SetJumpTarget(Less0);
	SetCC(CC_EQ);
		ORR(rA, rA, 1);
	SetCC();
	SetJumpTarget(SkipOrr0);

	VCMP(vB1);
	VMRS(_PC);
	FixupBranch Less1 = B_CC(CC_LT);
		VMOV(vD1, V0);
		SetFPException(fpscrReg, FPSCR_VXSQRT);
		FixupBranch SkipOrr1 = B();
	SetJumpTarget(Less1);
	SetCC(CC_EQ);
		ORR(rA, rA, 2);
	SetCC();
	SetJumpTarget(SkipOrr1);

	CMP(rA, 0);
	FixupBranch noException = B_CC(CC_EQ);
	SetFPException(fpscrReg, FPSCR_ZX);
	SetJumpTarget(noException);

	VCVT(S0, vB0, 0);
	VCVT(S1, vB1, 0);

	NEONXEmitter nemit(this);
	nemit.VRSQRTE(F_32, D0, D0);
	VCVT(vD0, S0, 0);
	VCVT(vD1, S1, 0);

	STR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
	gpr.Unlock(fpscrReg, rA);
}
コード例 #10
0
void JitArm::lwzx(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(LoadStore)

	ARMReg rA = gpr.GetReg();
	ARMReg rB = gpr.GetReg();

	ARMReg RB = gpr.R(inst.RB);
	ARMReg RD = gpr.R(inst.RD);
	LDR(rA, R9, PPCSTATE_OFF(Exceptions));
	CMP(rA, EXCEPTION_DSI);
	FixupBranch DoNotLoad = B_CC(CC_EQ);
	{
		if (inst.RA)
		{
			ARMReg RA = gpr.R(inst.RA);
			ADD(rB, RA, RB);
		}
		else
			MOV(rB, RB);
		
		MOVI2R(rA, (u32)&Memory::Read_U32);	
		PUSH(4, R0, R1, R2, R3);
		MOV(R0, rB);
		BL(rA);
		MOV(rA, R0);
		POP(4, R0, R1, R2, R3);
		MOV(RD, rA);
		gpr.Unlock(rA, rB);
	}
	SetJumpTarget(DoNotLoad);
	////	u32 temp = Memory::Read_U32(_inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB]);
}
コード例 #11
0
	void Jit::SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ARMReg tempReg, bool reverse) {
		SetR0ToEffectiveAddress(rs, offset);

		// There are three valid ranges.  Each one gets a bit.
		const u32 BIT_SCRATCH = 1, BIT_RAM = 2, BIT_VRAM = 4;
		MOVI2R(tempReg, BIT_SCRATCH | BIT_RAM | BIT_VRAM);

		CMP(R0, AssumeMakeOperand2(PSP_GetScratchpadMemoryBase()));
		SetCC(CC_LO);
		BIC(tempReg, tempReg, BIT_SCRATCH);
		SetCC(CC_HS);
		CMP(R0, AssumeMakeOperand2(PSP_GetScratchpadMemoryEnd()));
		BIC(tempReg, tempReg, BIT_SCRATCH);

		// If it was in that range, later compares don't matter.
		CMP(R0, AssumeMakeOperand2(PSP_GetVidMemBase()));
		SetCC(CC_LO);
		BIC(tempReg, tempReg, BIT_VRAM);
		SetCC(CC_HS);
		CMP(R0, AssumeMakeOperand2(PSP_GetVidMemEnd()));
		BIC(tempReg, tempReg, BIT_VRAM);

		CMP(R0, AssumeMakeOperand2(PSP_GetKernelMemoryBase()));
		SetCC(CC_LO);
		BIC(tempReg, tempReg, BIT_RAM);
		SetCC(CC_HS);
		CMP(R0, AssumeMakeOperand2(PSP_GetUserMemoryEnd()));
		BIC(tempReg, tempReg, BIT_RAM);

		// If we left any bit set, the address is OK.
		SetCC(CC_AL);
		CMP(tempReg, 0);
		SetCC(reverse ? CC_EQ : CC_GT);
	}
コード例 #12
0
void JitArm::UnsafeStoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset)
{
	// All this gets replaced on backpatch
	Operand2 mask(2, 1); // ~(Memory::MEMVIEW32_MASK)
	BIC(dest, dest, mask); // 1
	MOVI2R(R14, (u32)Memory::base, false); // 2-3
	ADD(dest, dest, R14); // 4
	switch (accessSize)
	{
		case 32:
			REV(value, value); // 5
		break;
		case 16:
			REV16(value, value);
		break;
		case 8:
			NOP(1);
		break;
	}
	switch (accessSize)
	{
		case 32:
			STR(value, dest); // 6
		break;
		case 16:
			STRH(value, dest);
		break;
		case 8:
			STRB(value, dest);
		break;
	}
	NOP(1); // 7
}
コード例 #13
0
ファイル: ppcEmitter.cpp プロジェクト: metalex10/PPSSPP-X360
	void PPCXEmitter::QuickCallFunction(void *func) {
		/** TODO : can use simple jump **/
		
		u32 func_addr = (u32) func;
		// Load func address
		MOVI2R(R0, func_addr);
		// Set it to link register
		MTCTR(R0);
		// Branch
		BCTRL();
	}
コード例 #14
0
void JitArm::mtmsr(UGeckoInstruction inst)
{
	INSTRUCTION_START
 	// Don't interpret this, if we do we get thrown out
	//JITDISABLE(SystemRegisters)
	
	ARMReg rA = gpr.GetReg();
	MOVI2R(rA, (u32)&MSR);
	STR(rA, gpr.R(inst.RS));
	gpr.Unlock(rA);
	WriteExit(js.compilerPC + 4, 0);
}
コード例 #15
0
ファイル: ppcEmitter.cpp プロジェクト: metalex10/PPSSPP-X360
	void PPCXEmitter::MOVI2F	(PPCReg dest, float imm, bool negate) {
		u32 tmp;

		union convert { 
			unsigned int i; 
			float f; 
		} fc;

		fc.f = imm;

		MOVI2R(R6, fc.i);

		// R7 = imm
		MOVI2R(R7, (u32)&tmp);
		STW(R6, R7);

		// dest = R7
		LFS(dest, R7, 0);

		if (negate == true) {
			FNEG(dest, dest);
		}
	}
コード例 #16
0
ファイル: ppcEmitter.cpp プロジェクト: metalex10/PPSSPP-X360
	void PPCXEmitter::SaveFloatSwap(PPCReg FRt, PPCReg Base, PPCReg offset) {
		// used for swapping float ...
		u32 tmp;

		// Save Value in tmp	
		MOVI2R(R7, (u32)&tmp);	
		SFS(FRt, R7, 0);

		// Load the value in R6
		LWZ(R6, R7); 
		
		// Save the final value
		STWBRX(R6, Base, offset); 
	}
コード例 #17
0
ファイル: ppcEmitter.cpp プロジェクト: metalex10/PPSSPP-X360
	void PPCXEmitter::LoadFloatSwap(PPCReg FRt, PPCReg Base, PPCReg offset) {
		// used for swapping float ...
		u32 tmp;
		
		// Load Value into a temp REG
		LWBRX(R6, Base, offset); 

		// Save it in tmp
		MOVI2R(R7, (u32)&tmp);
		STW(R6, R7);

		// Load the final value
		LFS(FRt, R7, 0);
	}
コード例 #18
0
void JitArm::lfs(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(LoadStoreFloating)
	Default(inst); return;

	ARMReg rA = gpr.GetReg();
	ARMReg rB = gpr.GetReg();
	LDR(rA, R9, STRUCT_OFF(PowerPC::ppcState, Exceptions));
	CMP(rA, EXCEPTION_DSI);
	FixupBranch DoNotLoad = B_CC(CC_EQ);

	if (inst.RA)
	{
		MOVI2R(rB, inst.SIMM_16);
		ARMReg RA = gpr.R(inst.RA);
		ADD(rB, rB, RA);
	}
	else
		MOVI2R(rB, (u32)inst.SIMM_16);

	MOVI2R(rA, (u32)&Memory::Read_U32);	
	PUSH(4, R0, R1, R2, R3);
	MOV(R0, rB);
	BL(rA);
	MOV(rA, R0);
	POP(4, R0, R1, R2, R3);
	
	ARMReg v0 = fpr.R0(inst.FD, false);
	ARMReg v1 = fpr.R1(inst.FD, false);
	
	VMOV(v0, rA, false);
	VMOV(v1, rA, false);

	gpr.Unlock(rA, rB);
	SetJumpTarget(DoNotLoad);
}
コード例 #19
0
void JitArm::mtspr(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(SystemRegisters)

	u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
	ARMReg RD = gpr.R(inst.RD);

	switch (iIndex)
	{
	case SPR_LR:
	case SPR_CTR:
	case SPR_XER:
		// These are safe to do the easy way, see the bottom of this function.
		break;

	case SPR_GQR0:
	case SPR_GQR0 + 1:
	case SPR_GQR0 + 2:
	case SPR_GQR0 + 3:
	case SPR_GQR0 + 4:
	case SPR_GQR0 + 5:
	case SPR_GQR0 + 6:
	case SPR_GQR0 + 7:
		// Prevent recompiler from compiling in old quantizer values.
		// If the value changed, destroy all blocks using this quantizer
		// This will create a little bit of block churn, but hopefully not too bad.
		{
			/*
			MOV(32, R(EAX), M(&PowerPC::ppcState.spr[iIndex]));  // Load old value
			CMP(32, R(EAX), gpr.R(inst.RD));
			FixupBranch skip_destroy = J_CC(CC_E, false);
			int gqr = iIndex - SPR_GQR0;
			ABI_CallFunctionC(ProtectFunction(&Jit64::DestroyBlocksWithFlag, 1), (u32)BLOCK_USE_GQR0 << gqr);
			SetJumpTarget(skip_destroy);*/
		}
		// TODO - break block if quantizers are written to.
	default:
		Default(inst);
		return;
	}

	// OK, this is easy.
	ARMReg rA = gpr.GetReg(false);
	MOVI2R(rA, (u32)&PowerPC::ppcState.spr);
	STR(rA, RD, iIndex * 4);
}
コード例 #20
0
ファイル: ppcEmitter.cpp プロジェクト: metalex10/PPSSPP-X360
	void PPCXEmitter::BLT (const void *fnptr) {
		//CHECK_JUMP
		if (!IS_SMALL_JUMP) {
			u32 func_addr = (u32) fnptr;
			// Load func address
			MOVI2R(R0, func_addr);
			// Set it to link register
			MTCTR(R0);
			// Branch
			BLTCTR();
			return;
		}

		s32 func =  (s32)fnptr - s32(code);
		u32 instr = (0x41800000 | (((s16)(((func)+1))) & 0xfffc));
		Write32(instr);
	}
コード例 #21
0
void JitArm::oris(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(Integer)
	u32 a = inst.RA, s = inst.RS;

	if (gpr.IsImm(s))
	{
		gpr.SetImmediate(a, gpr.GetImm(s) | (inst.UIMM << 16));
		return;
	}
	ARMReg RA = gpr.R(a);
	ARMReg RS = gpr.R(s);
	ARMReg rA = gpr.GetReg();
	MOVI2R(rA, inst.UIMM << 16);
	ORR(RA, RS, rA);
	gpr.Unlock(rA);
}
コード例 #22
0
void JitArm::mulli(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(Integer)
	u32 a = inst.RA, d = inst.RD;

	if (gpr.IsImm(a))
	{
		gpr.SetImmediate(d, gpr.GetImm(a) * inst.SIMM_16);
		return;
	}
	ARMReg RA = gpr.R(a);
	ARMReg RD = gpr.R(d);
	ARMReg rA = gpr.GetReg();
	MOVI2R(rA, inst.SIMM_16);
	MUL(RD, RA, rA);
	gpr.Unlock(rA);
}
コード例 #23
0
ファイル: JitArm_Paired.cpp プロジェクト: Catnips/dolphin
void JitArm::ps_res(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITPairedOff);
	FALLBACK_IF(inst.Rc);

	u32 b = inst.FB, d = inst.FD;

	ARMReg vB0 = fpr.R0(b);
	ARMReg vB1 = fpr.R1(b);
	ARMReg vD0 = fpr.R0(d, false);
	ARMReg vD1 = fpr.R1(d, false);
	ARMReg V0 = fpr.GetReg();
	MOVI2R(V0, 1.0, INVALID_REG); // temp reg not needed for 1.0

	VDIV(vD0, V0, vB0);
	VDIV(vD1, V0, vB1);
	fpr.Unlock(V0);
}
コード例 #24
0
void JitArm::andis_rc(UGeckoInstruction inst)
{
	u32 a = inst.RA, s = inst.RS;

	if (gpr.IsImm(s))
	{
		gpr.SetImmediate(a, gpr.GetImm(s) & ((u32)inst.UIMM << 16));
		ComputeRC(gpr.GetImm(a), 0); 
		return;
	}
	ARMReg rA = gpr.R(a);
	ARMReg rS = gpr.R(s);
	ARMReg RA = gpr.GetReg();

	MOVI2R(RA, (u32)inst.UIMM << 16);
	ANDS(rA, rS, RA);

	ComputeRC();
	gpr.Unlock(RA);
}
コード例 #25
0
void JitArm::addis(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(Integer)

	u32 d = inst.RD, a = inst.RA;
	if (a)
	{
		if (gpr.IsImm(a))
		{
			gpr.SetImmediate(d, gpr.GetImm(a) + (inst.SIMM_16 << 16));
			return;
		}
		ARMReg rA = gpr.GetReg(false);
		ARMReg RA = gpr.R(a);
		ARMReg RD = gpr.R(d);
		MOVI2R(rA, inst.SIMM_16 << 16);
		ADD(RD, RA, rA);
	}
	else
		gpr.SetImmediate(d, inst.SIMM_16 << 16);
}
コード例 #26
0
void JitArm::mfspr(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(SystemRegisters)

	u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
	ARMReg RD = gpr.R(inst.RD);
	switch (iIndex)
	{
	case SPR_WPAR:
	case SPR_DEC:
	case SPR_TL:
	case SPR_TU:
		Default(inst);
		return;
	default:
		ARMReg rA = gpr.GetReg(false);
		MOVI2R(rA, (u32)&PowerPC::ppcState.spr);
		LDR(RD, rA, iIndex * 4);
		break;
	}
}
コード例 #27
0
ファイル: ppcEmitter.cpp プロジェクト: metalex10/PPSSPP-X360
	void PPCXEmitter::Epilogue() {		
		u32 regSize = 8; // 4 in 32bit system
		u32 stackFrameSize = 0x1F0;

		//Break();

		// Write Epilogue (restore stack frame, return)
		// free stack
		ADDI(R1, R1, stackFrameSize);	
#if 0
		ADDI(R12, R1, -0x98);	

		// Restore fpr
		for(int i = 14; i < 32; i ++) {
			LFD((PPCReg)i, R1, -((32 - i) * regSize));
		}
#endif
		// Restore gpr
		for(int i = 14; i < 32; i ++) {
			LD((PPCReg)i, R1, -((33 - i) * regSize));
		}		

		// recover r12 (LR saved register)
		LWZ (R12, R1, -0x8);

		// Restore Lr
		MTLR(R12);
		
#if 1
		// load fpr buff
		MOVI2R(R5, (u32)&_fprTmp);
		
		// Load fpr
		for(int i = 14; i < 32; i ++) {
			LFD((PPCReg)i, R5, i * regSize);
		}
#endif
	}
コード例 #28
0
ファイル: ppcEmitter.cpp プロジェクト: metalex10/PPSSPP-X360
	void PPCXEmitter::Prologue() {
		// Save regs
		u32 regSize = 8; // 4 in 32bit system
		u32 stackFrameSize = 0x1F0;

		// Write Prologue (setup stack frame etc ...)
		// Save Lr
		MFLR(R12);

		// Save gpr
		for(int i = 14; i < 32; i ++) {
			STD((PPCReg)i, R1, -((33 - i) * regSize));
		}

		// Save r12
		STW(R12, R1, -0x8);
#if 0
		// add fpr frame
		ADDI(R12, R1, -0x98);
		
		// Load fpr
		for(int i = 14; i < 32; i ++) {
			SFD((PPCReg)i, R1, -((32 - i) * regSize));
		}
#endif
		// allocate stack
		STWU(R1, R1, -stackFrameSize);		

#if 1
		// load fpr buff
		MOVI2R(R10, (u32)&_fprTmp);
		
		// Save fpr
		for(int i = 14; i < 32; i ++) {
			SFD((PPCReg)i, R10, i * regSize);
		}
#endif
	}
コード例 #29
0
ファイル: ArmCompFPU.cpp プロジェクト: jack00/ppsspp
void Jit::Comp_FPULS(u32 op)
{
	CONDITIONAL_DISABLE;

	s32 offset = (s16)(op & 0xFFFF);
	int ft = _FT;
	int rs = _RS;
	// u32 addr = R(rs) + offset;
	// logBlocks = 1;
	bool doCheck = false;
	switch(op >> 26)
	{
	case 49: //FI(ft) = Memory::Read_U32(addr); break; //lwc1
		fpr.MapReg(ft, MAP_NOINIT | MAP_DIRTY);
		if (gpr.IsImm(rs)) {
			u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF;
			MOVI2R(R0, addr + (u32)Memory::base);
		} else {
			gpr.MapReg(rs);
			if (g_Config.bFastMemory) {
				SetR0ToEffectiveAddress(rs, offset);
			} else {
				SetCCAndR0ForSafeAddress(rs, offset, R1);
				doCheck = true;
			}
			ADD(R0, R0, R11);
		}
		VLDR(fpr.R(ft), R0, 0);
		if (doCheck) {
			SetCC(CC_EQ);
			MOVI2R(R0, 0);
			VMOV(fpr.R(ft), R0);
			SetCC(CC_AL);
		}
		break;

	case 57: //Memory::Write_U32(FI(ft), addr); break; //swc1
		fpr.MapReg(ft);
		if (gpr.IsImm(rs)) {
			u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF;
			MOVI2R(R0, addr + (u32)Memory::base);
		} else {
			gpr.MapReg(rs);
			if (g_Config.bFastMemory) {
				SetR0ToEffectiveAddress(rs, offset);
			} else {
				SetCCAndR0ForSafeAddress(rs, offset, R1);
				doCheck = true;
			}
			ADD(R0, R0, R11);
		}
		VSTR(fpr.R(ft), R0, 0);
		if (doCheck) {
			SetCC(CC_AL);
		}
		break;

	default:
		Comp_Generic(op);
		return;
	}
}
コード例 #30
0
ファイル: ArmCompFPU.cpp プロジェクト: jack00/ppsspp
void Jit::Comp_FPUComp(u32 op) {
	CONDITIONAL_DISABLE;
	int opc = op & 0xF;
	if (opc >= 8) opc -= 8; // alias
	if (opc == 0)//f, sf (signalling false)
	{
		MOVI2R(R0, 0);
		STR(R0, CTXREG, offsetof(MIPSState, fpcond));
		return;
	}

	int fs = _FS;
	int ft = _FT;
	fpr.MapInIn(fs, ft);
	VCMP(fpr.R(fs), fpr.R(ft));
	VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
	switch(opc)
	{
	case 1:      // un,  ngle (unordered)
		SetCC(CC_VS);
		MOVI2R(R0, 1);
		SetCC(CC_VC);
		break;
	case 2:      // eq,  seq (equal, ordered)
		SetCC(CC_EQ);
		MOVI2R(R0, 1);
		SetCC(CC_NEQ);
		break;
	case 3:      // ueq, ngl (equal, unordered)
		SetCC(CC_EQ);
		MOVI2R(R0, 1);
		SetCC(CC_NEQ);
		MOVI2R(R0, 0);
		SetCC(CC_VS);
		MOVI2R(R0, 1);
		SetCC(CC_AL);
		STR(R0, CTXREG, offsetof(MIPSState, fpcond));
		return;
	case 4:      // olt, lt (less than, ordered)
		SetCC(CC_LO);
		MOVI2R(R0, 1);
		SetCC(CC_HS);
		break;
	case 5:      // ult, nge (less than, unordered)
		SetCC(CC_LT);
		MOVI2R(R0, 1);
		SetCC(CC_GE);
		break;
	case 6:      // ole, le (less equal, ordered)
		SetCC(CC_LS);
		MOVI2R(R0, 1);
		SetCC(CC_HI);
		break;
	case 7:      // ule, ngt (less equal, unordered)
		SetCC(CC_LE);
		MOVI2R(R0, 1);
		SetCC(CC_GT);
		break;
	default:
		Comp_Generic(op);
		return;
	}
	MOVI2R(R0, 0);
	SetCC(CC_AL);
	STR(R0, CTXREG, offsetof(MIPSState, fpcond));
}