void JitILBase::subfx(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITIntegerOff);

	if (inst.OE)
		PanicAlert("OE: subfx");

	IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RB);
	val = ibuild.EmitSub(val, ibuild.EmitLoadGReg(inst.RA));
	ibuild.EmitStoreGReg(val, inst.RD);

	if (inst.Rc)
		ComputeRC(ibuild, val);
}
Beispiel #2
0
void JitILBase::rlwimix(UGeckoInstruction inst)
{
	INSTRUCTION_START
		JITDISABLE(bJITIntegerOff);
	unsigned mask = Helper_Mask(inst.MB, inst.ME);
	IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS);
	val = ibuild.EmitRol(val, ibuild.EmitIntConst(inst.SH));
	val = ibuild.EmitAnd(val, ibuild.EmitIntConst(mask));
	IREmitter::InstLoc ival = ibuild.EmitLoadGReg(inst.RA);
	ival = ibuild.EmitAnd(ival, ibuild.EmitIntConst(~mask));
	val = ibuild.EmitOr(ival, val);
	ibuild.EmitStoreGReg(val, inst.RA);

	if (inst.Rc)
		ComputeRC(ibuild, val);
}
Beispiel #3
0
void JitILBase::subfcx(UGeckoInstruction inst)
{
    INSTRUCTION_START
    JITDISABLE(bJITIntegerOff);
    if (inst.OE) PanicAlert("OE: subfcx");
    IREmitter::InstLoc val, test, lhs, rhs;
    lhs = ibuild.EmitLoadGReg(inst.RB);
    rhs = ibuild.EmitLoadGReg(inst.RA);
    val = ibuild.EmitSub(lhs, rhs);
    ibuild.EmitStoreGReg(val, inst.RD);
    test = ibuild.EmitICmpEq(rhs, ibuild.EmitIntConst(0));
    test = ibuild.EmitOr(test, ibuild.EmitICmpUgt(lhs, val));
    ibuild.EmitStoreCarry(test);
    if (inst.Rc)
        ComputeRC(ibuild, val);
}
Beispiel #4
0
void JitArm::addex(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(Integer)
	u32 a = inst.RA, b = inst.RB, d = inst.RD;
	Default(inst); return;
	ARMReg RA = gpr.R(a);
	ARMReg RB = gpr.R(b);
	ARMReg RD = gpr.R(d);
	ARMReg rA = gpr.GetReg();
	GetCarryAndClear(rA);
	ADDS(RD, RA, RB);
	FinalizeCarry(rA);
	if (inst.Rc) ComputeRC();
	gpr.Unlock(rA);
}
Beispiel #5
0
void JitILBase::srawix(UGeckoInstruction inst)
{
	INSTRUCTION_START
		JITDISABLE(bJITIntegerOff);
	// Shift right by two
	IREmitter::InstLoc input = ibuild.EmitLoadGReg(inst.RS);
	IREmitter::InstLoc output = ibuild.EmitSarl(input, ibuild.EmitIntConst(inst.SH));
	ibuild.EmitStoreGReg(output, inst.RA);
	// Check whether the input is negative and any bits got shifted out.
	unsigned int mask = -1u << inst.SH;
	IREmitter::InstLoc test = ibuild.EmitOr(input, ibuild.EmitIntConst(mask & 0x7FFFFFFF));
	test = ibuild.EmitICmpUgt(test, ibuild.EmitIntConst(mask));

	ibuild.EmitStoreCarry(test);
	if (inst.Rc)
		ComputeRC(ibuild, output);
}
Beispiel #6
0
void JitILBase::slwx(UGeckoInstruction inst)
{
    INSTRUCTION_START
    JITDISABLE(bJITIntegerOff);
    IREmitter::InstLoc val = ibuild.EmitLoadGReg(inst.RS),
                       samt = ibuild.EmitLoadGReg(inst.RB),
                       corr;
    // FIXME: We can do better with a cmov
    // FIXME: We can do better on 64-bit
    val = ibuild.EmitShl(val, samt);
    corr = ibuild.EmitShl(samt, ibuild.EmitIntConst(26));
    corr = ibuild.EmitSarl(corr, ibuild.EmitIntConst(31));
    corr = ibuild.EmitXor(corr, ibuild.EmitIntConst(-1));
    val = ibuild.EmitAnd(corr, val);
    ibuild.EmitStoreGReg(val, inst.RA);
    if (inst.Rc)
        ComputeRC(ibuild, val);
}
Beispiel #7
0
void JitArm::subfx(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(Integer)

	u32 a = inst.RA, b = inst.RB, d = inst.RD;
	
	if (inst.OE) PanicAlert("OE: subfx");

	if (gpr.IsImm(a) && gpr.IsImm(b))
	{
		gpr.SetImmediate(d, gpr.GetImm(b) - gpr.GetImm(a));
		if (inst.Rc) ComputeRC(gpr.GetImm(d), 0); 
		return;
	}
	ARMReg RA = gpr.R(a);
	ARMReg RB = gpr.R(b);
	ARMReg RD = gpr.R(d);
	SUBS(RD, RB, RA);
	if (inst.Rc) GenerateRC();
}
Beispiel #8
0
void Jit64::regimmop(int d, int a, bool binary, u32 value, Operation doop, void (XEmitter::*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc, bool carry)
{
	gpr.Lock(d, a);
	if (a || binary || carry)  // yeh nasty special case addic
	{
		if (gpr.R(a).IsImm() && !carry)
		{
			gpr.SetImmediate32(d, doop((u32)gpr.R(a).offset, value));
		}
		else if (a == d)
		{
			gpr.KillImmediate(d, true, true);
			(this->*op)(32, gpr.R(d), Imm32(value)); //m_GPR[d] = m_GPR[_inst.RA] + _inst.SIMM_16;
			if (carry)
				GenerateCarry();
		}
		else
		{
			gpr.BindToRegister(d, false);
			MOV(32, gpr.R(d), gpr.R(a));
			(this->*op)(32, gpr.R(d), Imm32(value)); //m_GPR[d] = m_GPR[_inst.RA] + _inst.SIMM_16;
			if (carry)
				GenerateCarry();
		}
	}
	else if (doop == Add)
	{
		// a == 0, which for these instructions imply value = 0
		gpr.SetImmediate32(d, value);
	}
	else
	{
		_assert_msg_(DYNA_REC, 0, "WTF regimmop");
	}
	if (Rc)
	{
		ComputeRC(gpr.R(d));
	}
	gpr.UnlockAll();
}
Beispiel #9
0
void JitILBase::addex(UGeckoInstruction inst)
{
    INSTRUCTION_START
    JITDISABLE(bJITIntegerOff);

    IREmitter::InstLoc a = ibuild.EmitLoadGReg(inst.RA);
    IREmitter::InstLoc b = ibuild.EmitLoadGReg(inst.RB);

    IREmitter::InstLoc ab = ibuild.EmitAdd(a, b);
    IREmitter::InstLoc new_carry = ibuild.EmitICmpUlt(ab, a);

    IREmitter::InstLoc previous_carry = ibuild.EmitLoadCarry();
    IREmitter::InstLoc abc = ibuild.EmitAdd(ab, previous_carry);
    new_carry = ibuild.EmitOr(new_carry, ibuild.EmitICmpUlt(abc, ab));

    ibuild.EmitStoreGReg(abc, inst.RD);
    ibuild.EmitStoreCarry(new_carry);

    if (inst.OE) PanicAlert("OE: addex");
    if (inst.Rc)
        ComputeRC(ibuild, abc);
}
Beispiel #10
0
void JitILBase::reg_imm(UGeckoInstruction inst)
{
	INSTRUCTION_START
		JITDISABLE(bJITIntegerOff);
	int d = inst.RD, a = inst.RA, s = inst.RS;
	IREmitter::InstLoc val, test, c;
	switch (inst.OPCD)
	{
	case 14:  // addi
		val = ibuild.EmitIntConst(inst.SIMM_16);
		if (a)
			val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), val);
		ibuild.EmitStoreGReg(val, d);
		break;
	case 15:  // addis
		val = ibuild.EmitIntConst(inst.SIMM_16 << 16);
		if (a)
			val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), val);
		ibuild.EmitStoreGReg(val, d);
		break;
	case 24:  // ori
		val = ibuild.EmitIntConst(inst.UIMM);
		val = ibuild.EmitOr(ibuild.EmitLoadGReg(s), val);
		ibuild.EmitStoreGReg(val, a);
		break;
	case 25:  // oris
		val = ibuild.EmitIntConst(inst.UIMM << 16);
		val = ibuild.EmitOr(ibuild.EmitLoadGReg(s), val);
		ibuild.EmitStoreGReg(val, a);
		break;
	case 28:  // andi
		val = ibuild.EmitIntConst(inst.UIMM);
		val = ibuild.EmitAnd(ibuild.EmitLoadGReg(s), val);
		ibuild.EmitStoreGReg(val, a);
		ComputeRC(ibuild, val);
		break;
	case 29:  // andis
		val = ibuild.EmitIntConst(inst.UIMM << 16);
		val = ibuild.EmitAnd(ibuild.EmitLoadGReg(s), val);
		ibuild.EmitStoreGReg(val, a);
		ComputeRC(ibuild, val);
		break;
	case 26:  // xori
		val = ibuild.EmitIntConst(inst.UIMM);
		val = ibuild.EmitXor(ibuild.EmitLoadGReg(s), val);
		ibuild.EmitStoreGReg(val, a);
		break;
	case 27:  // xoris
		val = ibuild.EmitIntConst(inst.UIMM << 16);
		val = ibuild.EmitXor(ibuild.EmitLoadGReg(s), val);
		ibuild.EmitStoreGReg(val, a);
		break;
	case 12:  // addic
	case 13:  // addic_rc
		c = ibuild.EmitIntConst(inst.SIMM_16);
		val = ibuild.EmitAdd(ibuild.EmitLoadGReg(a), c);
		ibuild.EmitStoreGReg(val, d);
		test = ibuild.EmitICmpUgt(c, val);
		ibuild.EmitStoreCarry(test);
		if (inst.OPCD == 13)
			ComputeRC(ibuild, val);
		break;
	default:
		FALLBACK_IF(true);
	}
}