Example #1
0
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);
}
void JitArm::fcmpu(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITFloatingPointOff)
	u32 a = inst.FA, b = inst.FB;
	int cr = inst.CRFD;

	ARMReg vA = fpr.R0(a);
	ARMReg vB = fpr.R0(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);
	FixupBranch Done4 = B();

	SetJumpTarget(NanA);
	SetJumpTarget(NanB);

	SetFPException(fpscrReg, FPSCR_VXSNAN);

	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);
}
Example #3
0
void JitArm::FinalizeCarry(ARMReg reg)
{
	ARMReg tmp = gpr.GetReg();
	Operand2 mask = Operand2(2, 2); // XER_CA_MASK
	SetCC(CC_CS);
	ORR(reg, reg, mask);
	SetCC();
	LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
	ORR(tmp, tmp, reg);
	STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
	gpr.Unlock(tmp);
}
void GGLAssembler::expand(integer_t& dst, const integer_t& src, int dbits)
{
    assert(src.size());

    int sbits = src.size();
    int s = src.reg;
    int d = dst.reg;

    // be sure to set 'dst' after we read 'src' as they may be identical
    dst.s = dbits;
    dst.flags = 0;

    if (dbits<=sbits) {
        if (s != d) {
            MOV(AL, 0, d, s);
        }
        return;
    }

    if (sbits == 1) {
        RSB(AL, 0, d, s, reg_imm(s, LSL, dbits));
            // d = (s<<dbits) - s;
        return;
    }

    if (dbits % sbits) {
        MOV(AL, 0, d, reg_imm(s, LSL, dbits-sbits));
            // d = s << (dbits-sbits);
        dbits -= sbits;
        do {
            ORR(AL, 0, d, d, reg_imm(d, LSR, sbits));
                // d |= d >> sbits;
            dbits -= sbits;
            sbits *= 2;
        } while(dbits>0);
        return;
    }
    
    dbits -= sbits;
    do {
        ORR(AL, 0, d, s, reg_imm(s, LSL, sbits));
            // d |= d<<sbits;
        s = d;        
        dbits -= sbits;
        if (sbits*2 < dbits) {
            sbits *= 2;
        }
    } while(dbits>0);
}
void GGLAssembler::load(const pointer_t& addr, const pixel_t& s, uint32_t flags)
{    
    Scratch scratches(registerFile());    
    int s0;

    const int bits = addr.size;
    const int inc = (flags & WRITE_BACK)?1:0;
    switch (bits) {
    case 32:
        if (inc)    LDR(AL, s.reg, addr.reg, immed12_post(4));
        else        LDR(AL, s.reg, addr.reg);
        break;
    case 24:
        // 24 bits formats are a little special and used only for RGB
        // R,G,B is packed as 0x00BBGGRR 
        s0 = scratches.obtain();
        if (s.reg != addr.reg) {
            LDRB(AL, s.reg, addr.reg, immed12_pre(0));      // R
            LDRB(AL, s0, addr.reg, immed12_pre(1));         // G
            ORR(AL, 0, s.reg, s.reg, reg_imm(s0, LSL, 8));
            LDRB(AL, s0, addr.reg, immed12_pre(2));         // B
            ORR(AL, 0, s.reg, s.reg, reg_imm(s0, LSL, 16));
        } else {
            int s1 = scratches.obtain();
            LDRB(AL, s1, addr.reg, immed12_pre(0));         // R
            LDRB(AL, s0, addr.reg, immed12_pre(1));         // G
            ORR(AL, 0, s1, s1, reg_imm(s0, LSL, 8));
            LDRB(AL, s0, addr.reg, immed12_pre(2));         // B
            ORR(AL, 0, s.reg, s1, reg_imm(s0, LSL, 16));
        }
        if (inc)
            ADD(AL, 0, addr.reg, addr.reg, imm(3));
        break;        
    case 16:
        if (inc)    LDRH(AL, s.reg, addr.reg, immed8_post(2));
        else        LDRH(AL, s.reg, addr.reg);
        break;
    case  8:
        if (inc)    LDRB(AL, s.reg, addr.reg, immed12_post(1));
        else        LDRB(AL, s.reg, addr.reg);
        break;
    }
}
Example #6
0
void JitArm::ComputeCarry()
{
	ARMReg tmp = gpr.GetReg();
	Operand2 mask = Operand2(2, 2); // XER_CA_MASK
	LDR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
	SetCC(CC_CS);
	ORR(tmp, tmp, mask);
	SetCC(CC_CC);
	BIC(tmp, tmp, mask);
	SetCC();
	STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER]));
	gpr.Unlock(tmp);
}
void JitArm64::crXXX(UGeckoInstruction inst)
{
  INSTRUCTION_START
  JITDISABLE(bJITSystemRegistersOff);

  // Special case: crclr
  if (inst.CRBA == inst.CRBB && inst.CRBA == inst.CRBD && inst.SUBOP10 == 193)
  {
    // Clear CR field bit
    int field = inst.CRBD >> 2;
    int bit = 3 - (inst.CRBD & 3);

    ARM64Reg WA = gpr.GetReg();
    ARM64Reg XA = EncodeRegTo64(WA);
    LDR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field);
    switch (bit)
    {
    case CR_SO_BIT:
      AND(XA, XA, 64 - 62, 62, true);  // XA & ~(1<<61)
      break;

    case CR_EQ_BIT:
      ORR(XA, XA, 0, 0, true);  // XA | 1<<0
      break;

    case CR_GT_BIT:
      ORR(XA, XA, 64 - 63, 0, true);  // XA | 1<<63
      break;

    case CR_LT_BIT:
      AND(XA, XA, 64 - 63, 62, true);  // XA & ~(1<<62)
      break;
    }
    STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field);
    gpr.Unlock(WA);
    return;
  }
Example #8
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);
}
void JitArm::fctiwx(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITFloatingPointOff)
	u32 b = inst.FB;
	u32 d = inst.FD;

	ARMReg vB = fpr.R0(b);
	ARMReg vD = fpr.R0(d);
	ARMReg V0 = fpr.GetReg();
	ARMReg V1 = fpr.GetReg();
	ARMReg V2 = fpr.GetReg();

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

	FixupBranch DoneMax, DoneMin;
	LDR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
	MOVI2R(rA, (u32)minmaxFloat);

	// Check if greater than max float
	{
		VLDR(V0, rA, 8); // Load Max
		VCMPE(vB, V0);
		VMRS(_PC); // Loads in to APSR
		FixupBranch noException = B_CC(CC_LE);
		VMOV(vD, V0); // Set to max
		SetFPException(fpscrReg, FPSCR_VXCVI);
		DoneMax = B();
		SetJumpTarget(noException);
	}
	// Check if less than min float
	{
		VLDR(V0, rA, 0);
		VCMPE(vB, V0);
		VMRS(_PC);
		FixupBranch noException = B_CC(CC_GE);
		VMOV(vD, V0);
		SetFPException(fpscrReg, FPSCR_VXCVI);
		DoneMin = B();
		SetJumpTarget(noException);
	}
	// Within ranges, convert to integer
	// Set rounding mode first
	// PPC <-> ARM rounding modes
	// 0, 1, 2, 3 <-> 0, 3, 1, 2
	ARMReg rB = gpr.GetReg();
	VMRS(rA);
	// Bits 22-23
	BIC(rA, rA, Operand2(3, 5));

	LDR(rB, R9, PPCSTATE_OFF(fpscr));
	AND(rB, rB, 0x3); // Get the FPSCR rounding bits
	CMP(rB, 1);
	SetCC(CC_EQ); // zero
		ORR(rA, rA, Operand2(3, 5));
	SetCC(CC_NEQ);
		CMP(rB, 2); // +inf
		SetCC(CC_EQ);
			ORR(rA, rA, Operand2(1, 5));
		SetCC(CC_NEQ);
			CMP(rB, 3); // -inf
			SetCC(CC_EQ);
				ORR(rA, rA, Operand2(2, 5));
	SetCC();
	VMSR(rA);
	ORR(rA, rA, Operand2(3, 5));
	VCVT(vD, vB, TO_INT | IS_SIGNED);
	VMSR(rA);
	gpr.Unlock(rB);
	VCMPE(vD, vB);
	VMRS(_PC);

	SetCC(CC_EQ);
		BIC(fpscrReg, fpscrReg, FRFIMask);
		FixupBranch DoneEqual = B();
	SetCC();
	SetFPException(fpscrReg, FPSCR_XX);
	ORR(fpscrReg, fpscrReg, FIMask);
	VABS(V1, vB);
	VABS(V2, vD);
	VCMPE(V2, V1);
	VMRS(_PC);
	SetCC(CC_GT);
		ORR(fpscrReg, fpscrReg, FRMask);
	SetCC();
	SetJumpTarget(DoneEqual);

	SetJumpTarget(DoneMax);
	SetJumpTarget(DoneMin);

	MOVI2R(rA, (u32)&doublenum);
	VLDR(V0, rA, 0);
	NEONXEmitter nemit(this);
	nemit.VORR(vD, vD, V0);

	if (inst.Rc) Helper_UpdateCR1(fpscrReg, rA);

	STR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
	gpr.Unlock(rA);
	gpr.Unlock(fpscrReg);
	fpr.Unlock(V0);
	fpr.Unlock(V1);
	fpr.Unlock(V2);
}
void JitArm::fctiwzx(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITFloatingPointOff)
	u32 b = inst.FB;
	u32 d = inst.FD;

	ARMReg vB = fpr.R0(b);
	ARMReg vD = fpr.R0(d);
	ARMReg V0 = fpr.GetReg();
	ARMReg V1 = fpr.GetReg();
	ARMReg V2 = fpr.GetReg();

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

	FixupBranch DoneMax, DoneMin;
	LDR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
	MOVI2R(rA, (u32)minmaxFloat);

	// Check if greater than max float
	{
		VLDR(V0, rA, 8); // Load Max
		VCMPE(vB, V0);
		VMRS(_PC); // Loads in to APSR
		FixupBranch noException = B_CC(CC_LE);
		VMOV(vD, V0); // Set to max
		SetFPException(fpscrReg, FPSCR_VXCVI);
		DoneMax = B();
		SetJumpTarget(noException);
	}
	// Check if less than min float
	{
		VLDR(V0, rA, 0);
		VCMPE(vB, V0);
		VMRS(_PC);
		FixupBranch noException = B_CC(CC_GE);
		VMOV(vD, V0);
		SetFPException(fpscrReg, FPSCR_VXCVI);
		DoneMin = B();
		SetJumpTarget(noException);
	}
	// Within ranges, convert to integer
	VCVT(vD, vB, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
	VCMPE(vD, vB);
	VMRS(_PC);

	SetCC(CC_EQ);
		BIC(fpscrReg, fpscrReg, FRFIMask);
		FixupBranch DoneEqual = B();
	SetCC();
	SetFPException(fpscrReg, FPSCR_XX);
	ORR(fpscrReg, fpscrReg, FIMask);
	VABS(V1, vB);
	VABS(V2, vD);
	VCMPE(V2, V1);
	VMRS(_PC);
	SetCC(CC_GT);
		ORR(fpscrReg, fpscrReg, FRMask);
	SetCC();
	SetJumpTarget(DoneEqual);

	SetJumpTarget(DoneMax);
	SetJumpTarget(DoneMin);

	MOVI2R(rA, (u32)&doublenum);
	VLDR(V0, rA, 0);
	NEONXEmitter nemit(this);
	nemit.VORR(vD, vD, V0);

	if (inst.Rc) Helper_UpdateCR1(fpscrReg, rA);

	STR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
	gpr.Unlock(rA);
	gpr.Unlock(fpscrReg);
	fpr.Unlock(V0);
	fpr.Unlock(V1);
	fpr.Unlock(V2);
}
void JitArm64::mfspr(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITSystemRegistersOff);

	u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
	int d = inst.RD;
	switch (iIndex)
	{
	case SPR_TL:
	case SPR_TU:
	{
		ARM64Reg WA = gpr.GetReg();
		ARM64Reg WB = gpr.GetReg();
		ARM64Reg XA = EncodeRegTo64(WA);
		ARM64Reg XB = EncodeRegTo64(WB);

		// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
		// cost of calling out to C for this is actually significant.
		MOVI2R(XA, (u64)&CoreTiming::globalTimer);
		LDR(INDEX_UNSIGNED, XA, XA, 0);
		MOVI2R(XB, (u64)&CoreTiming::fakeTBStartTicks);
		LDR(INDEX_UNSIGNED, XB, XB, 0);
		SUB(XA, XA, XB);

		// It might seem convenient to correct the timer for the block position here for even more accurate
		// timing, but as of currently, this can break games. If we end up reading a time *after* the time
		// at which an interrupt was supposed to occur, e.g. because we're 100 cycles into a block with only
		// 50 downcount remaining, some games don't function correctly, such as Karaoke Party Revolution,
		// which won't get past the loading screen.
		// a / 12 = (a * 0xAAAAAAAAAAAAAAAB) >> 67
		ORR(XB, SP, 1, 60);
		ADD(XB, XB, 1);
		UMULH(XA, XA, XB);

		MOVI2R(XB, (u64)&CoreTiming::fakeTBStartValue);
		LDR(INDEX_UNSIGNED, XB, XB, 0);
		ADD(XA, XB, XA, ArithOption(XA, ST_LSR, 3));
		STR(INDEX_UNSIGNED, XA, X29, PPCSTATE_OFF(spr[SPR_TL]));

		if (MergeAllowedNextInstructions(1))
		{
			const UGeckoInstruction& next = js.op[1].inst;
			// Two calls of TU/TL next to each other are extremely common in typical usage, so merge them
			// if we can.
			u32 nextIndex = (next.SPRU << 5) | (next.SPRL & 0x1F);
			// Be careful; the actual opcode is for mftb (371), not mfspr (339)
			int n = next.RD;
			if (next.OPCD == 31 && next.SUBOP10 == 371 && (nextIndex == SPR_TU || nextIndex == SPR_TL) && n != d)
			{
				js.downcountAmount++;
				js.skipInstructions = 1;
				gpr.BindToRegister(d, false);
				gpr.BindToRegister(n, false);
				if (iIndex == SPR_TL)
					MOV(gpr.R(d), WA);
				else
					ORR(EncodeRegTo64(gpr.R(d)), SP, XA, ArithOption(XA, ST_LSR, 32));

				if (nextIndex == SPR_TL)
					MOV(gpr.R(n), WA);
				else
					ORR(EncodeRegTo64(gpr.R(n)), SP, XA, ArithOption(XA, ST_LSR, 32));

				gpr.Unlock(WA, WB);
				break;
			}
		}
		gpr.BindToRegister(d, false);
		if (iIndex == SPR_TU)
			ORR(EncodeRegTo64(gpr.R(d)), SP, XA, ArithOption(XA, ST_LSR, 32));
		else
			MOV(gpr.R(d), WA);
		gpr.Unlock(WA, WB);
	}
	break;
	case SPR_XER:
	{
		gpr.BindToRegister(d, false);
		ARM64Reg RD = gpr.R(d);
		ARM64Reg WA = gpr.GetReg();
		LDRH(INDEX_UNSIGNED, RD, X29, PPCSTATE_OFF(xer_stringctrl));
		LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca));
		ORR(RD, RD, WA, ArithOption(WA, ST_LSL, XER_CA_SHIFT));
		LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_so_ov));
		ORR(RD, RD, WA, ArithOption(WA, ST_LSL, XER_OV_SHIFT));
		gpr.Unlock(WA);
	}
	break;
	case SPR_WPAR:
	case SPR_DEC:
		FALLBACK_IF(true);
	default:
		gpr.BindToRegister(d, false);
		ARM64Reg RD = gpr.R(d);
		LDR(INDEX_UNSIGNED, RD, X29, PPCSTATE_OFF(spr) + iIndex * 4);
		break;
	}
}
void JitArm64::twx(UGeckoInstruction inst)
{
	INSTRUCTION_START
	JITDISABLE(bJITSystemRegistersOff);

	s32 a = inst.RA;

	ARM64Reg WA = gpr.GetReg();

	if (inst.OPCD == 3) // twi
	{
		if (inst.SIMM_16 >= 0 && inst.SIMM_16 < 4096)
		{
			// Can fit in immediate in to the instruction encoding
			CMP(gpr.R(a), inst.SIMM_16);
		}
		else
		{
			MOVI2R(WA, (s32)(s16)inst.SIMM_16);
			CMP(gpr.R(a), WA);
		}
	}
	else // tw
	{
		CMP(gpr.R(a), gpr.R(inst.RB));
	}

	std::vector<FixupBranch> fixups;
	CCFlags conditions[] = { CC_LT, CC_GT, CC_EQ, CC_VC, CC_VS };

	for (int i = 0; i < 5; i++)
	{
		if (inst.TO & (1 << i))
		{
			FixupBranch f = B(conditions[i]);
			fixups.push_back(f);
		}
	}
	FixupBranch dont_trap = B();

	for (const FixupBranch& fixup : fixups)
	{
		SetJumpTarget(fixup);
	}

	gpr.Flush(FlushMode::FLUSH_MAINTAIN_STATE);
	fpr.Flush(FlushMode::FLUSH_MAINTAIN_STATE);

	LDR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(Exceptions));
	ORR(WA, WA, 24, 0); // Same as WA | EXCEPTION_PROGRAM
	STR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(Exceptions));

	MOVI2R(WA, js.compilerPC);

	// WA is unlocked in this function
	WriteExceptionExit(WA);

	SetJumpTarget(dont_trap);

	if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE))
	{
		gpr.Flush(FlushMode::FLUSH_ALL);
		fpr.Flush(FlushMode::FLUSH_ALL);
		WriteExit(js.compilerPC + 4);
	}
}
Example #13
0
	void Jit::Comp_ITypeMemLR(MIPSOpcode op, bool load) {
		CONDITIONAL_DISABLE;
		int offset = (signed short)(op & 0xFFFF);
		MIPSGPReg rt = _RT;
		MIPSGPReg rs = _RS;
		int o = op >> 26;

		if (!js.inDelaySlot) {
			// Optimisation: Combine to single unaligned load/store
			bool isLeft = (o == 34 || o == 42);
			MIPSOpcode nextOp = Memory::Read_Instruction(js.compilerPC + 4);
			// Find a matching shift in opposite direction with opposite offset.
			if (nextOp == (isLeft ? (op.encoding + (4<<26) - 3)
				                  : (op.encoding - (4<<26) + 3)))
			{
				EatInstruction(nextOp);
				nextOp = MIPSOpcode(((load ? 35 : 43) << 26) | ((isLeft ? nextOp : op) & 0x03FFFFFF)); //lw, sw
				Comp_ITypeMem(nextOp);
				return;
			}
		}

		u32 iaddr = gpr.IsImm(rs) ? offset + gpr.GetImm(rs) : 0xFFFFFFFF;
		bool doCheck = false;
		FixupBranch skip;

		if (gpr.IsImm(rs) && Memory::IsValidAddress(iaddr)) {
			u32 addr = iaddr & 0x3FFFFFFF;
			// Need to initialize since this only loads part of the register.
			// But rs no longer matters (even if rs == rt) since we have the address.
			gpr.MapReg(rt, load ? MAP_DIRTY : 0);
			gpr.SetRegImm(R0, addr & ~3);

			u8 shift = (addr & 3) * 8;

			switch (o) {
			case 34: // lwl
				LDR(R0, MEMBASEREG, R0);
				ANDI2R(gpr.R(rt), gpr.R(rt), 0x00ffffff >> shift, SCRATCHREG2);
				ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 24 - shift));
				break;

			case 38: // lwr
				LDR(R0, MEMBASEREG, R0);
				ANDI2R(gpr.R(rt), gpr.R(rt), 0xffffff00 << (24 - shift), SCRATCHREG2);
				ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSR, shift));
				break;

			case 42: // swl
				LDR(SCRATCHREG2, MEMBASEREG, R0);
				// Don't worry, can't use temporary.
				ANDI2R(SCRATCHREG2, SCRATCHREG2, 0xffffff00 << shift, R0);
				ORR(SCRATCHREG2, SCRATCHREG2, Operand2(gpr.R(rt), ST_LSR, 24 - shift));
				STR(SCRATCHREG2, MEMBASEREG, R0);
				break;

			case 46: // swr
				LDR(SCRATCHREG2, MEMBASEREG, R0);
				// Don't worry, can't use temporary.
				ANDI2R(SCRATCHREG2, SCRATCHREG2, 0x00ffffff >> (24 - shift), R0);
				ORR(SCRATCHREG2, SCRATCHREG2, Operand2(gpr.R(rt), ST_LSL, shift));
				STR(SCRATCHREG2, MEMBASEREG, R0);
				break;
			}
			return;
		}
Example #14
0
void JitArmILAsmRoutineManager::Generate()
{
	enterCode = GetCodePtr();
	PUSH(9, R4, R5, R6, R7, R8, R9, R10, R11, _LR);
	// Take care to 8-byte align stack for function calls.
	// We are misaligned here because of an odd number of args for PUSH.
	// It's not like x86 where you need to account for an extra 4 bytes
	// consumed by CALL.
	SUB(_SP, _SP, 4);

	MOVI2R(R0, (u32)&CoreTiming::downcount);
	MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]);

	FixupBranch skipToRealDispatcher = B();
	dispatcher = GetCodePtr();
		printf("ILDispatcher is %p\n", dispatcher);

		// Downcount Check
		// The result of slice decrementation should be in flags if somebody jumped here
		// IMPORTANT - We jump on negative, not carry!!!
		FixupBranch bail = B_CC(CC_MI);

		SetJumpTarget(skipToRealDispatcher);
		dispatcherNoCheck = GetCodePtr();

		// This block of code gets the address of the compiled block of code
		// It runs though to the compiling portion if it isn't found
			LDR(R12, R9, PPCSTATE_OFF(pc));// Load the current PC into R12

			Operand2 iCacheMask = Operand2(0xE, 2); // JIT_ICACHE_MASK
			BIC(R12, R12, iCacheMask); // R12 contains PC & JIT_ICACHE_MASK here.

			MOVI2R(R14, (u32)jit->GetBlockCache()->iCache);

			LDR(R12, R14, R12); // R12 contains iCache[PC & JIT_ICACHE_MASK] here
			// R12 Confirmed this is the correct iCache Location loaded.
			TST(R12, 0x80); // Test  to see if it is a JIT block.

			SetCC(CC_EQ);
				// Success, it is our Jitblock.
				MOVI2R(R14, (u32)jit->GetBlockCache()->GetCodePointers());
				// LDR R14 right here to get CodePointers()[0] pointer.
				LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size
				LDR(R14, R14, R12); // Load the block address in to R14

				B(R14);
				// No need to jump anywhere after here, the block will go back to dispatcher start
			SetCC();

		// If we get to this point, that means that we don't have the block cached to execute
		// So call ArmJit to compile the block and then execute it.
		MOVI2R(R14, (u32)&Jit);
		BL(R14);

		B(dispatcherNoCheck);

		// fpException()
		// Floating Point Exception Check, Jumped to if false
		fpException = GetCodePtr();
			LDR(R0, R9, PPCSTATE_OFF(Exceptions));
			ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE);
			STR(R0, R9, PPCSTATE_OFF(Exceptions));
				QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
			LDR(R0, R9, PPCSTATE_OFF(npc));
			STR(R0, R9, PPCSTATE_OFF(pc));
		B(dispatcher);

		SetJumpTarget(bail);
		doTiming = GetCodePtr();
		// XXX: In JIT64, Advance() gets called /after/ the exception checking
		// once it jumps back to the start of outerLoop
		QuickCallFunction(R14, (void*)&CoreTiming::Advance);

		// Does exception checking
		testExceptions = GetCodePtr();
			LDR(R0, R9, PPCSTATE_OFF(pc));
			STR(R0, R9, PPCSTATE_OFF(npc));
				QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
			LDR(R0, R9, PPCSTATE_OFF(npc));
			STR(R0, R9, PPCSTATE_OFF(pc));
		// Check the state pointer to see if we are exiting
		// Gets checked on every exception check
			MOVI2R(R0, (u32)PowerPC::GetStatePtr());
			MVN(R1, 0);
			LDR(R0, R0);
			TST(R0, R1);
			FixupBranch Exit = B_CC(CC_NEQ);

	B(dispatcher);

	SetJumpTarget(Exit);

	ADD(_SP, _SP, 4);

	POP(9, R4, R5, R6, R7, R8, R9, R10, R11, _PC);  // Returns

	GenerateCommon();

	FlushIcache();
}
Example #15
0
void decodeInstruction(instruction_t instruction, uint32_t *dir_reg, char *dir_flags, uint8_t *SRAM, uint16_t *dec)
{
	uint8_t *R_activos=instruction.registers_list;
	/* Comparacion de mnemonic y Llamado de las funciones */
	if( strcmp(instruction.mnemonic,"ADC") == 0 || strcmp(instruction.mnemonic,"ADCS") == 0){
		dir_reg[PC]++;
		*dec=16704;
		*dec=*dec|instruction.op3_value<<3|instruction.op1_value;
		dir_reg[instruction.op1_value]=ADC(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
	}

	if( strcmp(instruction.mnemonic,"ADDS") == 0 || strcmp(instruction.mnemonic,"ADD") == 0){
		dir_reg[PC]++;
		if(instruction.op2_type=='S'){
			*dec=45056;
			dir_reg[SP]=ADD(dir_reg[SP],instruction.op3_value,dir_flags);
			*dec=*dec|instruction.op3_value;}
		else if(instruction.op3_type=='#'){
			*dec=7168;
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;
			dir_reg[instruction.op1_value]=ADD(dir_reg[instruction.op2_value], instruction.op3_value,dir_flags);
			mvprintw(4,20,"%X",*dec);}
		else{
			*dec=6144;
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;
			dir_reg[instruction.op1_value]=ADD(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);}
	}
	
	if( strcmp(instruction.mnemonic,"AND") == 0 || strcmp(instruction.mnemonic,"ANDS") == 0){
		dir_reg[PC]++;
		*dec=16384;
		if(instruction.op3_type=='#'){
			dir_reg[instruction.op1_value]=AND(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);}
		else
			dir_reg[instruction.op1_value]=AND(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"ASR") == 0 || strcmp(instruction.mnemonic,"ASRS") == 0){
		dir_reg[PC]++;
		if(instruction.op3_type=='#'){
			*dec=4096;
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;
			dir_reg[instruction.op1_value]=ASR(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);}
		else{
			*dec=16640;
			*dec=*dec|instruction.op3_value<<3|instruction.op1_value;
			dir_reg[instruction.op1_value]=ASR(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);}
	}
	
	if( strcmp(instruction.mnemonic,"BICS") == 0 || strcmp(instruction.mnemonic,"BICS") == 0){
		dir_reg[PC]++;
		if(instruction.op3_type=='#')
			dir_reg[instruction.op1_value]=BIC(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);
		else{
			*dec=17280;
			dir_reg[instruction.op1_value]=BIC(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
			*dec=*dec|instruction.op3_value<<3|instruction.op1_value;}
	}
	
	if( strcmp(instruction.mnemonic,"CMN" ) == 0 || strcmp(instruction.mnemonic,"CMNS") == 0){
		dir_reg[PC]++;
		CMN(dir_reg[instruction.op1_value], dir_reg[instruction.op2_value],dir_flags);
		*dec=17088;
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
		mvprintw(4,20,"%X",*dec);
	}
	
	if( strcmp(instruction.mnemonic,"CMP") == 0 || strcmp(instruction.mnemonic,"CMPS") == 0){
		dir_reg[PC]++;
		CMP(dir_reg[instruction.op1_value],dir_reg[instruction.op2_value],dir_flags);
		*dec=17024;
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
		mvprintw(4,20,"%X",*dec);
	}
	
	if( strcmp(instruction.mnemonic,"EOR") == 0 || strcmp(instruction.mnemonic,"EORS") == 0){
		dir_reg[PC]++;
		*dec=16448;
		if(instruction.op3_type=='#')
			dir_reg[instruction.op1_value]=EOR(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);
		else
			dir_reg[instruction.op1_value]=EOR(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"LSLS") == 0 || strcmp(instruction.mnemonic,"LSL") == 0){
		dir_reg[PC]++;
		if(instruction.op3_type=='#'){
			*dec=0;
			dir_reg[instruction.op1_value]=LSL(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
		else{
			*dec=16512;
			dir_reg[instruction.op1_value]=LSL(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
			*dec=*dec|instruction.op3_value<<3|instruction.op1_value;}
	}
	
	if( strcmp(instruction.mnemonic,"LSRS") == 0 || strcmp(instruction.mnemonic,"LSR") == 0){
		dir_reg[PC]++;
		if(instruction.op3_type=='#'){
			*dec=2048;
			dir_reg[instruction.op1_value]=LSR(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
		else{
			*dec=16576;
			dir_reg[instruction.op1_value]=LSR(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
			*dec=*dec|instruction.op3_value<<3|instruction.op1_value;}
	}
	
	if( strcmp(instruction.mnemonic,"MOV") == 0 || strcmp(instruction.mnemonic,"MOVS") == 0){
		dir_reg[PC]++;
		if(instruction.op2_type=='#'){
			*dec=8192;
			dir_reg[instruction.op1_value]=MOV(instruction.op2_value,dir_flags);
			*dec=*dec|instruction.op1_value<<8|instruction.op2_value;}
		else{
			*dec=0;
			dir_reg[instruction.op1_value]=MOV(dir_reg[instruction.op2_value],dir_flags);
			*dec=*dec|instruction.op2_value<<3|instruction.op1_value;}
	}
	
	if( strcmp(instruction.mnemonic,"MUL") == 0 || strcmp(instruction.mnemonic,"MULS") == 0){
		dir_reg[PC]++;
		*dec=17216;
		if(instruction.op3_type=='#'){
			dir_reg[instruction.op1_value]=MUL(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);}
		else{
			dir_reg[instruction.op1_value]=MUL(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
			*dec=*dec|instruction.op2_value<<3|instruction.op1_value;}
	}
	
	if( strcmp(instruction.mnemonic,"MVN") == 0 || strcmp(instruction.mnemonic,"MVNS") == 0){
		dir_reg[PC]++;
		*dec=17344;
		dir_reg[instruction.op1_value]=MVN(dir_reg[instruction.op2_value], dir_flags);
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
	}
	
	if( strcmp(instruction.mnemonic,"ORR") == 0 || strcmp(instruction.mnemonic,"ORRS") == 0){
		dir_reg[PC]++;
		*dec=17152;
		if(instruction.op3_type=='#'){
			dir_reg[instruction.op1_value]=ORR(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);}
		else{
			dir_reg[instruction.op1_value]=ORR(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
			*dec=*dec|instruction.op3_value<<3|instruction.op1_value;}
	}
	
	if( strcmp(instruction.mnemonic,"REV") == 0 || strcmp(instruction.mnemonic,"REVS") == 0){
		dir_reg[PC]++;
		*dec=47616;
		dir_reg[instruction.op1_value]=REV(dir_reg[instruction.op2_value]);
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
	}
	
	if( strcmp(instruction.mnemonic,"REVG") == 0 || strcmp(instruction.mnemonic,"REVGS") == 0){
		dir_reg[PC]++;
		*dec=47680;
		dir_reg[instruction.op1_value]=REVG(dir_reg[instruction.op2_value]);
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
	}
	
	if( strcmp(instruction.mnemonic,"REVSH") == 0 || strcmp(instruction.mnemonic,"REVSHS") == 0){
		dir_reg[PC]++;
		*dec=47808;
		dir_reg[instruction.op1_value]=REVSH(dir_reg[instruction.op2_value]);
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
	}
	
	if( strcmp(instruction.mnemonic,"ROR") == 0 || strcmp(instruction.mnemonic,"RORS") == 0){
		dir_reg[PC]++;
		*dec=16832;
		if(instruction.op3_type=='#'){
			dir_reg[instruction.op1_value]=ROR(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);}
		else{
			dir_reg[instruction.op1_value]=ROR(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
			*dec=*dec|instruction.op3_value<<3|instruction.op1_value;}
	}
	
	if( strcmp(instruction.mnemonic,"RSB") == 0 || strcmp(instruction.mnemonic,"RSBS") == 0){
		dir_reg[PC]++;
		*dec=16690;
		dir_reg[instruction.op1_value]=RSB(dir_reg[instruction.op2_value], dir_flags);
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
	}
	
	if( strcmp(instruction.mnemonic,"SBC") == 0 || strcmp(instruction.mnemonic,"SBCS") == 0){
		dir_reg[PC]++;
		*dec=16768;
		SBC(dir_reg[instruction.op1_value],dir_reg[instruction.op2_value], dir_flags);
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
	}
	
	if( strcmp(instruction.mnemonic,"SUBS") == 0 || strcmp(instruction.mnemonic,"SUB") == 0){
		dir_reg[PC]++;
		if(instruction.op2_type=='S'){
			*dec=45184;
			dir_reg[SP]=SUB(dir_reg[SP],instruction.op3_value,dir_flags);
			*dec=*dec|instruction.op3_value;}
		else if(instruction.op3_type=='#'){
			*dec=7680;
			dir_reg[instruction.op1_value]=SUB(dir_reg[instruction.op2_value],instruction.op3_value,dir_flags);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
		else{
			*dec=6656;
			dir_reg[instruction.op1_value]=SUB(dir_reg[instruction.op2_value],dir_reg[instruction.op3_value],dir_flags);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
	}
	
	if( strcmp(instruction.mnemonic,"TST") == 0 || strcmp(instruction.mnemonic,"TSTS") == 0){
		dir_reg[PC]++;
		*dec=16896;
		TST(dir_reg[instruction.op1_value], dir_reg[instruction.op2_value], dir_flags);
		*dec=*dec|instruction.op2_value<<3|instruction.op1_value;
	}
	
	if( strcmp(instruction.mnemonic,"NOP") == 0 ){
		NOP(dir_reg);
		*dec=48896;
	}
	
	if( strcmp(instruction.mnemonic,"B") == 0 ){
		*dec=57344;
		*dec=*dec|instruction.op1_value;
		B(instruction.op1_value, dir_reg);
	}
	
	if( strcmp(instruction.mnemonic,"BL") == 0 ){
		*dec=0;
		BL(instruction.op1_value, dir_reg);
	}
	
	if( strcmp(instruction.mnemonic,"BX") == 0 ){
		*dec=18176;
		BX(dir_reg);
	}
	
	if( strcmp(instruction.mnemonic,"BEQ") == 0 ){
		*dec=0;
		BEQ(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BNE") == 0 ){
		*dec=0;
		BNE(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BCS") == 0 ){
		*dec=0;
		BCS(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BCC") == 0 ){
		*dec=0;
		BCC(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BMI") == 0 ){
		*dec=0;
		BMI(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BPL") == 0 ){
		*dec=0;
		BPL(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BVS") == 0 ){
		*dec=0;
		BVS(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BVC") == 0 ){
		*dec=0;
		BVC(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BHI") == 0 ){
		*dec=0;
		BHI(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BLS") == 0 ){
		*dec=0;
		BLS(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BGE") == 0 ){
		*dec=0;
		BGE(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BLT") == 0 ){
		*dec=0;
		BLT(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BGT") == 0 ){
		*dec=0;
		BGT(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BLE") == 0 ){
		*dec=0;
		BLE(instruction.op1_value, dir_reg, dir_flags);
	}
	
	if( strcmp(instruction.mnemonic,"BAL") == 0 ){
		*dec=0;
		BAL(instruction.op1_value, dir_reg);
	}
	
	if(strcmp(instruction.mnemonic,"PUSH")==0){
		dir_reg[PC]++;
		*dec=46080;
		PUSH(SRAM, dir_reg,R_activos);
	}
	
	if(strcmp(instruction.mnemonic,"POP")==0){
		dir_reg[PC]++;
		*dec=48128;
		POP(SRAM,dir_reg,R_activos);
	}
	
	data=(uint8_t)dir_reg[instruction.op1_value];
	if(strcmp(instruction.mnemonic,"LDR")==0){
		dir_reg[PC]++;
		if(instruction.op2_type=='=' && instruction.op3_type=='N'){
			*dec=0;
			dir_reg[instruction.op1_value]=instruction.op2_value;}
		else if(instruction.op2_type=='S'){
			*dec=38912;
			dir_reg[instruction.op1_value]=LDR(dir_reg[SP], instruction.op3_value<<2, SRAM);
			*dec=*dec|instruction.op3_value|instruction.op1_value<<8;}
		else if(instruction.op3_type=='#' || instruction.op3_type=='N'){
			*dec=26624;
			if((dir_reg[instruction.op2_value]+(instruction.op3_value<<2))>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+(instruction.op3_value<<2)), &data,Read);
			else
				dir_reg[instruction.op1_value]=LDR(dir_reg[instruction.op2_value], instruction.op3_value<<2, SRAM);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value|instruction.op1_value;}
		else{
			*dec=22528;
			if((dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value])>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value]), &data,Read);
			else
				dir_reg[instruction.op1_value]=LDR(dir_reg[instruction.op2_value], dir_reg[instruction.op3_value], SRAM);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
	}
	
	if(strcmp(instruction.mnemonic,"LDRB")==0){
		dir_reg[PC]++;
		if(instruction.op3_type=='#' || instruction.op3_type=='N'){
			*dec=30720;
			if((dir_reg[instruction.op2_value]+instruction.op3_value)>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+instruction.op3_value), &data,Read);	
			else
				dir_reg[instruction.op1_value]=LDRB(dir_reg[instruction.op2_value], instruction.op3_value, SRAM);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
		else{
			*dec=23552;
			if((dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value])>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value]), &data,Read);
			else 
				dir_reg[instruction.op1_value]=LDRB(dir_reg[instruction.op2_value], dir_reg[instruction.op3_value], SRAM);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
	}
	
	if(strcmp(instruction.mnemonic,"LDRH")==0){
		dir_reg[PC]++;
		if(instruction.op3_type=='#' || instruction.op3_type=='N'){
			*dec=34816;
			if((dir_reg[instruction.op2_value]+(instruction.op3_value<<1))>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+(instruction.op3_value<<1)), &data,Read);
			else
				dir_reg[instruction.op1_value]=LDRH(dir_reg[instruction.op2_value], instruction.op3_value<<1, SRAM);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
		else{
			*dec=23040;
			if((dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value])>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value]), &data,Read);
			else
				dir_reg[instruction.op1_value]=LDRH(dir_reg[instruction.op2_value], dir_reg[instruction.op3_value], SRAM);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
	}
	
	if(strcmp(instruction.mnemonic,"LDRSB")==0){
		dir_reg[PC]++;
		*dec=22016;
		*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;
		if((dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value])>=0x40000000)
			IOAccess((uint8_t)(dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value]), &data,Read);
		else
			dir_reg[instruction.op1_value]=LDRSB(dir_reg[instruction.op2_value], dir_reg[instruction.op3_value], SRAM);
	}
	
	if(strcmp(instruction.mnemonic,"LDRSH")==0){
		dir_reg[PC]++;
		*dec=24064;
		*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;
		if((dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value])>=0x40000000)
			IOAccess((uint8_t)(dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value]), &data,Read);
		else
			dir_reg[instruction.op1_value]=LDRSH(dir_reg[instruction.op2_value], dir_reg[instruction.op3_value], SRAM);
	}
	
	if(strcmp(instruction.mnemonic,"STR")==0){
		dir_reg[PC]++;
		if(instruction.op2_type=='S'){
			*dec=38912;
			STR(dir_reg[instruction.op1_value],dir_reg[SP], instruction.op3_value<<2, SRAM);
			*dec=*dec|instruction.op3_value|instruction.op1_value<<8;}
		else if(instruction.op3_type=='#' || instruction.op3_type=='N'){
			*dec=24576;
			if((dir_reg[instruction.op2_value]+(instruction.op3_value<<2))>=0x40000000){
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+(instruction.op3_value<<2)), &data,Write);}
			else{
				STR(dir_reg[instruction.op1_value], dir_reg[instruction.op2_value], instruction.op3_value<<2, SRAM);}
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;
			mvprintw(1,3,"Hola");}
		else{
			*dec=20480;
			if((dir_reg[instruction.op2_value]+dir_reg[instruction.op2_value])>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+(dir_reg[instruction.op3_value])), &data,Write);
			else{
				STR(dir_reg[instruction.op1_value], instruction.op2_value, instruction.op3_value, SRAM);}
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
	}
	
	if(strcmp(instruction.mnemonic,"STRB")==0){
		dir_reg[PC]++;
		if(instruction.op3_type=='#' || instruction.op3_type=='N'){
			*dec=28672;
			if(dir_reg[instruction.op2_value]+instruction.op3_value>=0x40000000){
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+instruction.op3_value), &data,Write);}
			else{			
				STRB(dir_reg[instruction.op1_value], dir_reg[instruction.op2_value], instruction.op3_value, SRAM);}
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
		else{
			*dec=21504;
			if((dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value])>=0x40000000){
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+(dir_reg[instruction.op3_value])), &data,Write);}
			else{
				STRB(dir_reg[instruction.op1_value], dir_reg[instruction.op2_value], dir_reg[instruction.op3_value], SRAM);}
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
	}
	
	if(strcmp(instruction.mnemonic,"STRH")==0){
		dir_reg[PC]++;
		if(instruction.op3_type=='#' || instruction.op3_type=='N'){
			*dec=32768;
			if(((dir_reg[instruction.op2_value])+(instruction.op3_value<<1))>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+(instruction.op3_value<<1)),&data,Write);
			else
				STRH(dir_reg[instruction.op1_value], dir_reg[instruction.op2_value], instruction.op3_value<<1, SRAM);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
		else{
			*dec=20992;
			if((dir_reg[instruction.op2_value]+dir_reg[instruction.op3_value])>=0x40000000)
				IOAccess((uint8_t)(dir_reg[instruction.op2_value]+(dir_reg[instruction.op3_value])), &data,Write);
			else
				STRH(dir_reg[instruction.op1_value], dir_reg[instruction.op2_value], dir_reg[instruction.op3_value], SRAM);
			*dec=*dec|instruction.op3_value<<6|instruction.op2_value<<3|instruction.op1_value;}
	}
}
void GGLAssembler::downshift(
        pixel_t& d, int component, component_t s, const reg_t& dither)
{
    const needs_t& needs = mBuilderContext.needs;
    Scratch scratches(registerFile());

    int sh = s.h;
    int sl = s.l;
    int maskHiBits = (sh!=32) ? ((s.flags & CLEAR_HI)?1:0) : 0;
    int maskLoBits = (sl!=0)  ? ((s.flags & CLEAR_LO)?1:0) : 0;
    int sbits = sh - sl;

    int dh = d.format.c[component].h;
    int dl = d.format.c[component].l;
    int dbits = dh - dl;
    int dithering = 0;
    
    ALOGE_IF(sbits<dbits, "sbits (%d) < dbits (%d) in downshift", sbits, dbits);

    if (sbits>dbits) {
        // see if we need to dither
        dithering = mDithering;
    }
    
    int ireg = d.reg;
    if (!(d.flags & FIRST)) {
        if (s.flags & CORRUPTIBLE)  {
            ireg = s.reg;
        } else {
            ireg = scratches.obtain();
        }
    }
    d.flags &= ~FIRST;

    if (maskHiBits) {
        // we need to mask the high bits (and possibly the lowbits too)
        // and we might be able to use immediate mask.
        if (!dithering) {
            // we don't do this if we only have maskLoBits because we can
            // do it more efficiently below (in the case where dl=0)
            const int offset = sh - dbits;
            if (dbits<=8 && offset >= 0) {
                const uint32_t mask = ((1<<dbits)-1) << offset;
                if (isValidImmediate(mask) || isValidImmediate(~mask)) {
                    build_and_immediate(ireg, s.reg, mask, 32);
                    sl = offset;
                    s.reg = ireg; 
                    sbits = dbits;
                    maskLoBits = maskHiBits = 0;
                }
            }
        } else {
            // in the dithering case though, we need to preserve the lower bits
            const uint32_t mask = ((1<<sbits)-1) << sl;
            if (isValidImmediate(mask) || isValidImmediate(~mask)) {
                build_and_immediate(ireg, s.reg, mask, 32);
                s.reg = ireg; 
                maskLoBits = maskHiBits = 0;
            }
        }
    }

    // XXX: we could special case (maskHiBits & !maskLoBits)
    // like we do for maskLoBits below, but it happens very rarely
    // that we have maskHiBits only and the conditions necessary to lead
    // to better code (like doing d |= s << 24)

    if (maskHiBits) {
        MOV(AL, 0, ireg, reg_imm(s.reg, LSL, 32-sh));
        sl += 32-sh;
        sh = 32;
        s.reg = ireg;
        maskHiBits = 0;
    }

    //	Downsampling should be performed as follows:
    //  V * ((1<<dbits)-1) / ((1<<sbits)-1)
    //	V * [(1<<dbits)/((1<<sbits)-1)	-	1/((1<<sbits)-1)]
    //	V * [1/((1<<sbits)-1)>>dbits	-	1/((1<<sbits)-1)]
    //	V/((1<<(sbits-dbits))-(1>>dbits))	-	(V>>sbits)/((1<<sbits)-1)>>sbits
    //	V/((1<<(sbits-dbits))-(1>>dbits))	-	(V>>sbits)/(1-(1>>sbits))
    //
    //	By approximating (1>>dbits) and (1>>sbits) to 0:
    //
    //		V>>(sbits-dbits)	-	V>>sbits
    //
	//  A good approximation is V>>(sbits-dbits),
    //  but better one (needed for dithering) is:
    //
    //		(V>>(sbits-dbits)<<sbits	-	V)>>sbits
    //		(V<<dbits	-	V)>>sbits
    //		(V	-	V>>dbits)>>(sbits-dbits)

    // Dithering is done here
    if (dithering) {
        comment("dithering");
        if (sl) {
            MOV(AL, 0, ireg, reg_imm(s.reg, LSR, sl));
            sh -= sl;
            sl = 0;
            s.reg = ireg; 
        }
        // scaling (V-V>>dbits)
        SUB(AL, 0, ireg, s.reg, reg_imm(s.reg, LSR, dbits));
        const int shift = (GGL_DITHER_BITS - (sbits-dbits));
        if (shift>0)        ADD(AL, 0, ireg, ireg, reg_imm(dither.reg, LSR, shift));
        else if (shift<0)   ADD(AL, 0, ireg, ireg, reg_imm(dither.reg, LSL,-shift));
        else                ADD(AL, 0, ireg, ireg, dither.reg);
        s.reg = ireg; 
    }

    if ((maskLoBits|dithering) && (sh > dbits)) {
        int shift = sh-dbits;
        if (dl) {
            MOV(AL, 0, ireg, reg_imm(s.reg, LSR, shift));
            if (ireg == d.reg) {
                MOV(AL, 0, d.reg, reg_imm(ireg, LSL, dl));
            } else {
                ORR(AL, 0, d.reg, d.reg, reg_imm(ireg, LSL, dl));
            }
        } else {
            if (ireg == d.reg) {
                MOV(AL, 0, d.reg, reg_imm(s.reg, LSR, shift));
            } else {
                ORR(AL, 0, d.reg, d.reg, reg_imm(s.reg, LSR, shift));
            }
        }
    } else {
        int shift = sh-dh;
        if (shift>0) {
            if (ireg == d.reg) {
                MOV(AL, 0, d.reg, reg_imm(s.reg, LSR, shift));
            } else {
                ORR(AL, 0, d.reg, d.reg, reg_imm(s.reg, LSR, shift));
            }
        } else if (shift<0) {
            if (ireg == d.reg) {
                MOV(AL, 0, d.reg, reg_imm(s.reg, LSL, -shift));
            } else {
                ORR(AL, 0, d.reg, d.reg, reg_imm(s.reg, LSL, -shift));
            }
        } else {
            if (ireg == d.reg) {
                if (s.reg != d.reg) {
                    MOV(AL, 0, d.reg, s.reg);
                }
            } else {
                ORR(AL, 0, d.reg, d.reg, s.reg);
            }
        }
    }
}
Example #17
0
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;
	}
}
Example #18
0
void decodeInstruction(instruction_t instruction,unsigned long *r[],unsigned long *bandera,unsigned long *PC,unsigned long*LR,uint8_t*memoria,unsigned long *codificacion)
{
    int auxban;
    unsigned long aux1,aux2,des;
	//            codificacion funciones de la alu
	if(strcmp(instruction.mnemonic,"ADDS") == 0)
	{
		if(instruction.op1_type=='R')
        {
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
            {
				r[instruction.op1_value]=ADD(r[instruction.op2_value],r[instruction.op3_value],&bandera);
			}
            if((instruction.op2_type== '#' )&&(instruction.op3_type =='R' ))
            {
				r[instruction.op1_value]=ADD(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='#' ))
            {
				r[instruction.op1_value]=ADD(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
            if((instruction.op2_type== '#' )&&(instruction.op3_type =='#' ))
			{
				r[instruction.op1_value]=ADD(instruction.op2_value,instruction.op3_value,&bandera);
            }
            mostrar(r[instruction.op1_value]);
        }
		if(instruction.op1_type=='N')
		{
			if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
			{
				ADD(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
				ADD(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
				ADD(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
				ADD(instruction.op2_value,instruction.op3_value,&bandera);
            }
			mostrar(r[instruction.op1_value]);
		}
	}
	if(strcmp(instruction.mnemonic,"CMN") == 0)
	{
        if((instruction.op1_type== 'R' )&&(instruction.op2_type =='R' ))
        {
            ADD(r[instruction.op1_value],r[instruction.op2_value],&bandera);
        }
        if((instruction.op1_type == '#' )&&(instruction.op2_type== 'R' ))
        {
            ADD(instruction.op1_value,r[instruction.op2_value],&bandera);
        }
        if((instruction.op1_type == 'R' )&&(instruction.op2_type == '#' ))
        {
            ADD(r[instruction.op1_value],instruction.op2_value,&bandera);
        }
        if((instruction.op1_type == '#' )&&(instruction.op2_type == '#' ))
        {
            ADD(instruction.op1_value,instruction.op2_value,&bandera);
        }
	}
	if( strcmp(instruction.mnemonic,"ADCS") == 0)
	{
		if(instruction.op1_type=='R')
		{
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
			{
				r[instruction.op1_value]=ADC(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
            if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
			{
				r[instruction.op1_value]=ADC(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
            if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
			{
                r[instruction.op1_value]=ADC(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
            if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
				r[instruction.op1_value]=ADC(instruction.op2_value,instruction.op3_value,&bandera);
            }
			mostrar(r[instruction.op1_value]);
		}
        if(instruction.op1_type=='N')
        {
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
            {
				ADC(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
				ADC(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
				ADC(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
				ADC(instruction.op2_value,instruction.op3_value,&bandera);
            }
            mostrar(r[instruction.op1_value]);
		}
    }
    if( strcmp(instruction.mnemonic,"ANDS") == 0)
    {
        if(instruction.op1_type=='R')
        {
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
            {
                r[instruction.op1_value]=AND(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
            if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
                r[instruction.op1_value]=AND(instruction.op2_value,r[instruction.op3_value],&bandera);
			}
            if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
                r[instruction.op1_value]=AND(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
                r[instruction.op1_value]=AND(instruction.op2_value,instruction.op3_value,&bandera);
            }
           mostrar(r[instruction.op1_value]);
		}
        if(instruction.op1_type=='N')
        {
			if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
			{
                AND(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
                AND(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
                AND(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
                AND(instruction.op2_value,instruction.op3_value,&bandera);
            }
            mostrar(r[instruction.op1_value]);
		}
    }
    if(strcmp(instruction.mnemonic,"TEST") == 0)
    {
        if((instruction.op1_type== 'R' )&&(instruction.op2_type =='R' ))
        {
            AND(r[instruction.op1_value],r[instruction.op2_value],&bandera);
        }
        if((instruction.op1_type == '#' )&&(instruction.op2_type== 'R' ))
        {
            AND(instruction.op1_value,r[instruction.op2_value],&bandera);
        }
        if((instruction.op1_type == 'R' )&&(instruction.op2_type == '#' ))
        {
            AND(r[instruction.op1_value],instruction.op2_value,&bandera);
        }
        if((instruction.op1_type == '#' )&&(instruction.op2_type == '#' ))
        {
            AND(instruction.op1_value,instruction.op2_value,&bandera);
        }
    }
    if( strcmp(instruction.mnemonic,"EORS") == 0)
    {
        if(instruction.op1_type=='R')
       {
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
			{
                r[instruction.op1_value]=EOR(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
            if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
			{
                r[instruction.op1_value]=EOR(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
                r[instruction.op1_value]=EOR(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
            if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
                r[instruction.op1_value]=EOR(instruction.op2_value,instruction.op3_value,&bandera);
            }
           mostrar(r[instruction.op1_value]);
		}
        if(instruction.op1_type=='N')
        {
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
            {
                EOR(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
				EOR(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
				EOR(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
                EOR(instruction.op2_value,instruction.op3_value,&bandera);
            }
			mostrar(r[instruction.op1_value]);
		}
    }
    if( (strcmp(instruction.mnemonic,"MOVS") == 0)||(strcmp(instruction.mnemonic,"MOV") == 0))
    {

		if((instruction.op1_type == 'R')&&(instruction.op2_type=='R') )
		{
			r[instruction.op1_value]=MOV(r[instruction.op1_value],r[instruction.op2_value],&bandera);
			mostrar(r[instruction.op1_value]);
		}
        if((instruction.op1_type == 'R')&&(instruction.op2_type=='#') )
        {
            r[instruction.op1_value]=MOV(instruction.op1_value,instruction.op2_value,&bandera);
            mostrar(r[instruction.op1_value]);
        }
    }
    if( strcmp(instruction.mnemonic,"ORRS") == 0)
    {
        if(instruction.op1_type=='R')
        {
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
            {
                r[instruction.op1_value]=ORR(r[instruction.op2_value],r[instruction.op3_value],&bandera);
			}
            if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
                r[instruction.op1_value]=ORR(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
            if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
                r[instruction.op1_value]=ORR(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
                r[instruction.op1_value]=ORR(instruction.op2_value,instruction.op3_value,&bandera);
            }
			mostrar(r[instruction.op1_value]);
		}
        if(instruction.op1_type=='N')
        {
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
            {
                ORR(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
                ORR(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
				ORR(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
                ORR(instruction.op2_value,instruction.op3_value,&bandera);
            }
			mostrar(r[instruction.op1_value]);
        }
    }
	if( strcmp(instruction.mnemonic,"SUBS") == 0)
    {
        if(instruction.op1_type== 'R' )
		{
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
            {
                r[instruction.op1_value]=SUB(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
            if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
                r[instruction.op1_value]=SUB(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
           if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
                r[instruction.op1_value]=SUB(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
                r[instruction.op1_value]=SUB(instruction.op2_value,instruction.op3_value,&bandera);
            }
			mostrar(r[instruction.op1_value]);
		}
        if(instruction.op1_type=='N')
        {
            if((instruction.op2_type== 'R' )&&(instruction.op3_type =='R' ))
			{
                SUB(r[instruction.op2_value],r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type== 'R' ))
            {
                SUB(instruction.op2_value,r[instruction.op3_value],&bandera);
            }
			if((instruction.op2_type == 'R' )&&(instruction.op3_type == '#' ))
            {
                SUB(r[instruction.op2_value],instruction.op3_value,&bandera);
            }
			if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
            {
                SUB(instruction.op2_value,instruction.op3_value,&bandera);
            }
			mostrar(r[instruction.op1_value]);
        }
    }
    if(strcmp(instruction.mnemonic,"CMP") == 0)
    {
        if((instruction.op1_type== 'R' )&&(instruction.op2_type =='R' ))
        {
            SUB(r[instruction.op1_value],r[instruction.op2_value],&bandera);
        }
        if((instruction.op1_type == '#' )&&(instruction.op2_type== 'R' ))
        {
            SUB(instruction.op1_value,r[instruction.op2_value],&bandera);
        }
        if((instruction.op1_type == 'R' )&&(instruction.op2_type == '#' ))
		{
            SUB(r[instruction.op1_value],instruction.op2_value,&bandera);
        }
		if((instruction.op2_type == '#' )&&(instruction.op3_type == '#' ))
        {
            SUB(instruction.op1_value,instruction.op2_value,&bandera);
        }
    }
    //                 decodificacion funciones branch
	if(strcmp(instruction.mnemonic,"B")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(28<<11)+(instruction.op1_value);
			B(&PC,instruction.op1_value);
		}
	}
	if(strcmp(instruction.mnemonic,"BEQ")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(instruction.op1_value);
			BEQ(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BNE")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(1<<8)+(instruction.op1_value);
			BNE(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BCS")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(2<<8)+(instruction.op1_value);
			BCS(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BCC")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(3<<8)+(instruction.op1_value);
			BCC(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BMI")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(4<<8)+(instruction.op1_value);
			BMI(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BPL")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(5<<8)+(instruction.op1_value);
			BPL(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BVS")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(6<<8)+(instruction.op1_value);
			BVS(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BVC")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(2<<7)+(instruction.op1_value);
			BVC(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BHI")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(8<<8)+(instruction.op1_value);
			BHI(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BLS")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(9<<8)+(instruction.op1_value);
			BLS(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BGE")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(10<<8)+(instruction.op1_value);
			BGE(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BLT")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(11<<8)+(instruction.op1_value);
			BLT(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BGT")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(12<<8)+(instruction.op1_value);
			BGT(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BLE")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(13<<11)+(13<<8)+(instruction.op1_value);
			BLE(&PC,instruction.op1_value,&bandera);
		}
	}
	if(strcmp(instruction.mnemonic,"BL")==0)
	{
		if(instruction.op1_type=='#')
		{
			*codificacion=(31<<11)+(2047&instruction.op1_value+(((1<<31)&instruction.op1_value)>>20));
			BL(&PC,instruction.op1_value,&LR);
		}
	}