コード例 #1
0
ファイル: ArmCompFPU.cpp プロジェクト: DonelBueno/ppsspp
void Jit::Comp_mxc1(u32 op)
{
	CONDITIONAL_DISABLE;

	int fs = _FS;
	int rt = _RT;

	switch ((op >> 21) & 0x1f)
	{
	case 0: // R(rt) = FI(fs); break; //mfc1
		// Let's just go through RAM for now.
		fpr.FlushR(fs);
		gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT);
		LDR(gpr.R(rt), CTXREG, fpr.GetMipsRegOffset(fs));
		return;

	case 2: //cfc1
		if (fs == 31)
		{
			gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT);
			LDR(R0, CTXREG, offsetof(MIPSState, fpcond));
			AND(R0, R0, Operand2(1)); // Just in case
			LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
			BIC(gpr.R(rt), gpr.R(rt), Operand2(0x1 << 23));
			ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 23));
		}
		else if (fs == 0)
		{
			gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT);
			LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr0));
		}
		return;

	case 4: //FI(fs) = R(rt);	break; //mtc1
		// Let's just go through RAM for now.
		gpr.FlushR(rt);
		fpr.MapReg(fs, MAP_DIRTY | MAP_NOINIT);
		VLDR(fpr.R(fs), CTXREG, gpr.GetMipsRegOffset(rt));
		return;

	case 6: //ctc1
		if (fs == 31)
		{
			gpr.MapReg(rt, 0);
			// Hardware rounding method.
			// Left here in case it is faster than conditional method.
			/*
			AND(R0, gpr.R(rt), Operand2(3));
			// MIPS Rounding Mode <-> ARM Rounding Mode
			//         0, 1, 2, 3 <->  0, 3, 1, 2
			CMP(R0, Operand2(1));
			SetCC(CC_EQ); ADD(R0, R0, Operand2(2));
			SetCC(CC_GT); SUB(R0, R0, Operand2(1));
			SetCC(CC_AL);

			// Load and Store RM to FPSCR
			VMRS(R1);
			BIC(R1, R1, Operand2(0x3 << 22));
			ORR(R1, R1, Operand2(R0, ST_LSL, 22));
			VMSR(R1);
			*/
			// Update MIPS state
			STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
			MOV(R0, Operand2(gpr.R(rt), ST_LSR, 23));
			AND(R0, R0, Operand2(1));
			STR(R0, CTXREG, offsetof(MIPSState, fpcond));
		}
		return;
	}
}
コード例 #2
0
ファイル: ArmCompFPU.cpp プロジェクト: DonelBueno/ppsspp
void Jit::Comp_FPU2op(u32 op)
{
	CONDITIONAL_DISABLE;

	int fs = _FS;
	int fd = _FD;

	switch (op & 0x3f) 
	{
	case 4:	//F(fd)	   = sqrtf(F(fs));            break; //sqrt
		fpr.MapDirtyIn(fd, fs);
		VSQRT(fpr.R(fd), fpr.R(fs));
		break;
	case 5:	//F(fd)    = fabsf(F(fs));            break; //abs
		fpr.MapDirtyIn(fd, fs);
		VABS(fpr.R(fd), fpr.R(fs));
		break;
	case 6:	//F(fd)	   = F(fs);                   break; //mov
		fpr.MapDirtyIn(fd, fs);
		VMOV(fpr.R(fd), fpr.R(fs));
		break;
	case 7:	//F(fd)	   = -F(fs);                  break; //neg
		fpr.MapDirtyIn(fd, fs);
		VNEG(fpr.R(fd), fpr.R(fs));
		break;
	case 12: //FsI(fd) = (int)floorf(F(fs)+0.5f); break; //round.w.s
		fpr.MapDirtyIn(fd, fs);
		VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
		break;
	case 13: //FsI(fd) = Rto0(F(fs)));            break; //trunc.w.s
		fpr.MapDirtyIn(fd, fs);
		VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
		break;
	case 14: //FsI(fd) = (int)ceilf (F(fs));      break; //ceil.w.s
		fpr.MapDirtyIn(fd, fs);
		MOVI2F(S0, 0.5f, R0);
		VADD(S0,fpr.R(fs),S0);
		VCVT(fpr.R(fd), S0,        TO_INT | IS_SIGNED);
		break;
	case 15: //FsI(fd) = (int)floorf(F(fs));      break; //floor.w.s
		fpr.MapDirtyIn(fd, fs);
		MOVI2F(S0, 0.5f, R0);
		VSUB(S0,fpr.R(fs),S0);
		VCVT(fpr.R(fd), S0,        TO_INT | IS_SIGNED);
		break;
	case 32: //F(fd)   = (float)FsI(fs);          break; //cvt.s.w
		fpr.MapDirtyIn(fd, fs);
		VCVT(fpr.R(fd), fpr.R(fs), TO_FLOAT | IS_SIGNED);
		break;
	case 36: //FsI(fd) = (int)  F(fs);            break; //cvt.w.s
		fpr.MapDirtyIn(fd, fs);
		LDR(R0, CTXREG, offsetof(MIPSState, fcr31));
		AND(R0, R0, Operand2(3));
		// MIPS Rounding Mode:
		//	 0: Round nearest
		//	 1: Round to zero
		//	 2: Round up (ceil)
		//	 3: Round down (floor)
		CMP(R0, Operand2(2));
		SetCC(CC_GE); MOVI2F(S0, 0.5f, R1);
		SetCC(CC_GT); VSUB(S0,fpr.R(fs),S0);
		SetCC(CC_EQ); VADD(S0,fpr.R(fs),S0);
		SetCC(CC_GE); VCVT(fpr.R(fd), S0, TO_INT | IS_SIGNED); /* 2,3 */
		SetCC(CC_AL);
		CMP(R0, Operand2(1));
		SetCC(CC_EQ); VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO); /* 1 */
		SetCC(CC_LT); VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED); /* 0 */
		SetCC(CC_AL);
		break;
	default:
		DISABLE;
	}
}
コード例 #3
0
void JitArm::ps_cmpo1(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITFloatingPointOff);
	u32 a = inst.FA, b = inst.FB;
	int cr = inst.CRFD;

	ARMReg vA = fpr.R1(a);
	ARMReg vB = fpr.R1(b);
	ARMReg fpscrReg = gpr.GetReg();
	ARMReg crReg = gpr.GetReg();
	Operand2 FPRFMask(0x1F, 0xA); // 0x1F000
	Operand2 LessThan(0x8, 0xA); // 0x8000
	Operand2 GreaterThan(0x4, 0xA); // 0x4000
	Operand2 EqualTo(0x2, 0xA); // 0x2000
	Operand2 NANRes(0x1, 0xA); // 0x1000
	FixupBranch Done1, Done2, Done3;
	LDR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
	BIC(fpscrReg, fpscrReg, FPRFMask);

	VCMPE(vA, vB);
	VMRS(_PC);
	SetCC(CC_LT);
		ORR(fpscrReg, fpscrReg, LessThan);
		MOV(crReg,  8);
		Done1 = B();
	SetCC(CC_GT);
		ORR(fpscrReg, fpscrReg, GreaterThan);
		MOV(crReg,  4);
		Done2 = B();
	SetCC(CC_EQ);
		ORR(fpscrReg, fpscrReg, EqualTo);
		MOV(crReg,  2);
		Done3 = B();
	SetCC();

	ORR(fpscrReg, fpscrReg, NANRes);
	MOV(crReg,  1);

	VCMPE(vA, vA);
	VMRS(_PC);
	FixupBranch NanA = B_CC(CC_NEQ);
	VCMPE(vB, vB);
	VMRS(_PC);
	FixupBranch NanB = B_CC(CC_NEQ);

	SetFPException(fpscrReg, FPSCR_VXVC);
	FixupBranch Done4 = B();

	SetJumpTarget(NanA);
	SetJumpTarget(NanB);

	SetFPException(fpscrReg, FPSCR_VXSNAN);

	TST(fpscrReg, VEMask);

	FixupBranch noVXVC = B_CC(CC_NEQ);
	SetFPException(fpscrReg, FPSCR_VXVC);

	SetJumpTarget(noVXVC);
	SetJumpTarget(Done1);
	SetJumpTarget(Done2);
	SetJumpTarget(Done3);
	SetJumpTarget(Done4);
	STRB(crReg, R9, PPCSTATE_OFF(cr_fast) + cr);
	STR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
	gpr.Unlock(fpscrReg, crReg);
}
コード例 #4
0
ファイル: c-codegen-expr.c プロジェクト: yogesharora/Minicc
int assignExprCodegen(c_tree tree, int *registerNo, int topLevel,
		int getAddress, const char *breakLabel, const char *continueLabel)
{
	c_tree rhs = TREE_EXPR_OPERAND(tree,1);
	c_tree lhs = TREE_EXPR_OPERAND(tree,0);
	if (TREE_CODE(lhs) == TREE_DECL && (strcmp(DECL_NAME_STRING(lhs), COUT)
			== 0))
	{
		int rhsValue = c_codegen_recurse(rhs, registerNo, FALSE, FALSE,
				breakLabel, continueLabel);
		ADDi(R0, rhsValue, 0, "copying into R0", NULL);
		COUTASM("Displaying to COUT", "");
		return R0;
	}
	else
	{

		c_tree type = get_type_for_uid(TYPE(TREE_TYPE(lhs))->uid);
		int typeSize = getSize(TREE_TYPE(lhs));

		if(TYPE(type)->code!=STRUCT_TYPE || typeSize==1 )
		{
			int rhsValue = c_codegen_recurse(rhs, registerNo, FALSE, FALSE,
					breakLabel, continueLabel);
			int lhsAddress = c_codegen_recurse(lhs, registerNo, FALSE, TRUE,
					breakLabel, continueLabel);
			STRi(rhsValue, lhsAddress, 0, "assignment", NULL);
		}
		else
		{

			int rhsAddress = c_codegen_recurse(rhs, registerNo, FALSE, TRUE,
					breakLabel, continueLabel);
			int lhsAddress = c_codegen_recurse(lhs, registerNo, FALSE, TRUE,
					breakLabel, continueLabel);

			static int copyCondLabelNo = 0;
			static char copyCondLabelPrefix[] = "SCC";
			char copyCondLabelArray[LABEL_ARRAY_LENGTH];

			static int copyEndLabelNo = 0;
			static char copyEndLabelPrefix[] = "SCE";
			char copyEndLabelArray[LABEL_ARRAY_LENGTH];

			sprintf(copyCondLabelArray, "%s%d", copyCondLabelPrefix,
					copyCondLabelNo++);
			sprintf(copyEndLabelArray, "%s%d", copyEndLabelPrefix,
								copyEndLabelNo++);

			int counterRegister = (*registerNo)++;
			int subResultRegister = (*registerNo)++;
			int tempCopyRegister = (*registerNo)++;

			// loop for copying
			SET(counterRegister, 0, "struct copy counter initial value", NULL);
			SUBi(subResultRegister, counterRegister, typeSize,
					"struct copy condition to end copying", copyCondLabelArray);
			BRnzp(subResultRegister, copyEndLabelArray,
					"struct copy branch to end", NULL, "z");
			LDR(tempCopyRegister, rhsAddress, counterRegister, "struct assignment", NULL);
			STR(tempCopyRegister, lhsAddress, counterRegister, "struct assignment", NULL);
			ADDi(counterRegister, counterRegister, 1, "struct copy increment counter", NULL);
			BRA(copyCondLabelArray, "struct copy branch to condition", NULL);
			NOP("end of struct copying", copyEndLabelArray);

		}

		return c_codegen_recurse(lhs, registerNo,
				topLevel, getAddress, breakLabel, continueLabel);
	}
}
コード例 #5
0
void JitArm::lXX(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITLoadStoreOff)

	u32 a = inst.RA, b = inst.RB, d = inst.RD;
	s32 offset = inst.SIMM_16;
	u32 accessSize = 0;
	s32 offsetReg = -1;
	bool zeroA = true;
	bool update = false;
	bool signExtend = false;
	bool reverse = false;
	bool fastmem = false;

	switch(inst.OPCD)
	{
		case 31:
			switch(inst.SUBOP10)
			{
				case 55: // lwzux
					zeroA = false;
					update = true;
				case 23: // lwzx
					accessSize = 32;
					offsetReg = b;
				break;
				case 119: //lbzux
					zeroA = false;
					update = true;
				case 87: // lbzx
					accessSize = 8;
					offsetReg = b;
				break;
				case 311: // lhzux
					zeroA = false;
					update = true;
				case 279: // lhzx
					accessSize = 16;
					offsetReg = b;
				break;
				case 375: // lhaux
					zeroA = false;
					update = true;
				case 343: // lhax
					accessSize = 16;
					signExtend = true;
					offsetReg = b;
				break;
				case 534: // lwbrx
					accessSize = 32;
					reverse = true;
				break;
				case 790: // lhbrx
					accessSize = 16;
					reverse = true;
				break;
			}
		break;
		case 33: // lwzu
			zeroA = false;
			update = true;
		case 32: // lwz
			fastmem = true;
			accessSize = 32;
		break;
		case 35: // lbzu
			zeroA = false;
			update = true;
		case 34: // lbz
			fastmem = true;
			accessSize = 8;
		break;
		case 41: // lhzu
			zeroA = false;
			update = true;
		case 40: // lhz
			fastmem = true;
			accessSize = 16;
		break;
		case 43: // lhau
			zeroA = false;
			update = true;
		case 42: // lha
			signExtend = true;
			accessSize = 16;
		break;
	}

	// Check for exception before loading
	ARMReg rA = gpr.GetReg(false);

	LDR(rA, R9, PPCSTATE_OFF(Exceptions));
	CMP(rA, EXCEPTION_DSI);
	FixupBranch DoNotLoad = B_CC(CC_EQ);

	SafeLoadToReg(fastmem, d, zeroA ? a ? a : -1 : a, offsetReg, accessSize, offset, signExtend, reverse);

	if (update)
	{
		rA = gpr.GetReg(false);
		ARMReg RA = gpr.R(a);
		if (offsetReg == -1)
			MOVI2R(rA, offset);
		else
			MOV(RA, gpr.R(offsetReg));
		ADD(RA, RA, rA);
	}

	SetJumpTarget(DoNotLoad);

	// LWZ idle skipping
	if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
		inst.OPCD == 32 &&
		(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)
	{
		ARMReg RD = gpr.R(d);
		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[a] + (s32)(s16)inst.SIMM_16);
		BL(rA);

		gpr.Unlock(rA);
		WriteExceptionExit();

		SetJumpTarget(noIdle);

		//js.compilerPC += 8;
		return;
	}

}
コード例 #6
0
void JitArm::stX(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITLoadStoreOff)

	u32 a = inst.RA, b = inst.RB, s = inst.RS;
	s32 offset = inst.SIMM_16;
	u32 accessSize = 0;
	s32 regOffset = -1;
	bool zeroA = true;
	bool update = false;
	bool fastmem = false;
	switch(inst.OPCD)
	{
		case 45: // sthu
			update = true;
		case 44: // sth
			accessSize = 16;
		break;
		case 31:
			switch (inst.SUBOP10)
			{
				case 183: // stwux
					zeroA = false;
					update = true;
				case 151: // stwx
					fastmem = true;
					accessSize = 32;
					regOffset = b;
				break;
				case 247: // stbux
					zeroA = false;
					update = true;
				case 215: // stbx
					accessSize = 8;
					regOffset = b;
				break;
				case 439: // sthux
					zeroA = false;
					update = true;
				case 407: // sthx
					accessSize = 16;
					regOffset = b;
				break;
			}
		break;
		case 37: // stwu
			update = true;
		case 36: // stw
			fastmem = true;
			accessSize = 32;
		break;
		case 39: // stbu
			update = true;
		case 38: // stb
			accessSize = 8;
		break;
	}
	SafeStoreFromReg(fastmem, zeroA ? a ? a : -1 : a, s, regOffset, accessSize, offset);
	if (update)
	{
		ARMReg rA = gpr.GetReg();
		ARMReg RB;
		ARMReg RA = gpr.R(a);
		if (regOffset != -1)
			RB = gpr.R(regOffset);
		// Check for DSI exception prior to writing back address
		LDR(rA, R9, PPCSTATE_OFF(Exceptions));
		CMP(rA, EXCEPTION_DSI);
		FixupBranch DoNotWrite = B_CC(CC_EQ);
		if (a)
		{
			if (regOffset == -1)
				MOVI2R(rA, offset);
			else
				MOV(rA, RB);
			ADD(RA, RA, rA);
		}
		else
			if (regOffset == -1)
				MOVI2R(RA, (u32)offset);
			else
				MOV(RA, RB);
		SetJumpTarget(DoNotWrite);
		gpr.Unlock(rA);
	}
}