Beispiel #1
0
bool mips3_frontend::describe_cop2(UINT32 op, opcode_desc &desc)
{
	// any COP2 instruction can potentially cause an exception
	desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;

	switch (RSREG)
	{
		case 0x00:  // MFCz
		case 0x01:  // DMFCz
		case 0x02:  // CFCz
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x04:  // MTCz
		case 0x05:  // DMTCz
		case 0x06:  // CTCz
			desc.regin[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x08:  // BC
			switch (RTREG)
			{
				case 0x00:  // BCzF
				case 0x01:  // BCzT
					desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
					desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
					desc.delayslots = 1;
					return true;
			}
			return false;
	}

	return false;
}
Beispiel #2
0
static int describe_instruction_cop2(mips3_state *mipsaa, UINT32 op, opcode_desc *desc)
{
	/* any COP2 instruction can potentially cause an exception */
	desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;

	switch (RSREG)
	{
		case 0x00:	/* MFCz */
		case 0x01:	/* DMFCz */
		case 0x02:	/* CFCz */
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x04:	/* MTCz */
		case 0x05:	/* DMTCz */
		case 0x06:	/* CTCz */
			desc->regin[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x08:	/* BC */
			switch (RTREG)
			{
				case 0x00:	/* BCzF */
				case 0x01:	/* BCzT */
					desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
					desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
					desc->delayslots = 1;
					return TRUE;
			}
			return FALSE;
	}

	return FALSE;
}
Beispiel #3
0
bool sh2_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
    INT32 disp;

    switch ( opcode  & (15<<8) )
    {
    case  0 << 8: // MOVBS4(opcode & 0x0f, Rm);
    case  1 << 8: // MOVWS4(opcode & 0x0f, Rm);
        desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
        desc.flags |= OPFLAG_WRITES_MEMORY;
        return true;

    case  2<< 8: // NOP();
    case  3<< 8: // NOP();
    case  6<< 8: // NOP();
    case  7<< 8: // NOP();
    case 10<< 8: // NOP();
    case 12<< 8: // NOP();
    case 14<< 8: // NOP();
        return true;

    case  4<< 8: // MOVBL4(Rm, opcode & 0x0f);
    case  5<< 8: // MOVWL4(Rm, opcode & 0x0f);
        desc.regin[0] |= REGFLAG_R(Rm);
        desc.regout[0] |= REGFLAG_R(0);
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;

    case  8<< 8: // CMPIM(opcode & 0xff);
        desc.regin[0] |= REGFLAG_R(Rm);
        desc.regin[1] |= REGFLAG_SR;
        desc.regout[1] |= REGFLAG_SR;
        return true;

    case  9<< 8: // BT(opcode & 0xff);
    case 11<< 8: // BF(opcode & 0xff);
        desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
        desc.cycles = 3;
        disp = ((INT32)opcode << 24) >> 24;
        desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
        return true;

    case 13<< 8: // BTS(opcode & 0xff);
    case 15<< 8: // BFS(opcode & 0xff);
        desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
        desc.cycles = 2;
        disp = ((INT32)opcode << 24) >> 24;
        desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
        desc.delayslots = 1;
        return true;
    }

    return false;
}
Beispiel #4
0
static int describe_instruction_regimm(mips3_state *mipsaa, UINT32 op, opcode_desc *desc)
{
	switch (RTREG)
	{
		case 0x00:	/* BLTZ */
		case 0x01:	/* BGEZ */
		case 0x02:	/* BLTZL */
		case 0x03:	/* BGEZL */
			if (RTREG == 0x01 && RSREG == 0)
				desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc->regin[0] |= REGFLAG_R(RSREG);
				desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
			desc->delayslots = 1;
			desc->skipslots = (RTREG & 0x02) ? 1 : 0;
			return TRUE;

		case 0x08:	/* TGEI */
		case 0x09:	/* TGEIU */
		case 0x0a:	/* TLTI */
		case 0x0b:	/* TLTIU */
		case 0x0c:	/* TEQI */
		case 0x0e:	/* TNEI */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x10:	/* BLTZAL */
		case 0x11:	/* BGEZAL */
		case 0x12:	/* BLTZALL */
		case 0x13:	/* BGEZALL */
			if (RTREG == 0x11 && RSREG == 0)
				desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc->regin[0] |= REGFLAG_R(RSREG);
				desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc->regout[0] |= REGFLAG_R(31);
			desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
			desc->delayslots = 1;
			desc->skipslots = (RTREG & 0x02) ? 1 : 0;
			return TRUE;
	}

	return FALSE;
}
Beispiel #5
0
bool mips3_frontend::describe_regimm(UINT32 op, opcode_desc &desc)
{
	switch (RTREG)
	{
		case 0x00:  // BLTZ
		case 0x01:  // BGEZ
		case 0x02:  // BLTZL
		case 0x03:  // BGEZL
			if (RTREG == 0x01 && RSREG == 0)
				desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc.regin[0] |= REGFLAG_R(RSREG);
				desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
			desc.delayslots = 1;
			desc.skipslots = (RTREG & 0x02) ? 1 : 0;
			return true;

		case 0x08:  // TGEI
		case 0x09:  // TGEIU
		case 0x0a:  // TLTI
		case 0x0b:  // TLTIU
		case 0x0c:  // TEQI
		case 0x0e:  // TNEI
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x10:  // BLTZAL
		case 0x11:  // BGEZAL
		case 0x12:  // BLTZALL
		case 0x13:  // BGEZALL
			if (RTREG == 0x11 && RSREG == 0)
				desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc.regin[0] |= REGFLAG_R(RSREG);
				desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc.regout[0] |= REGFLAG_R(31);
			desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
			desc.delayslots = 1;
			desc.skipslots = (RTREG & 0x02) ? 1 : 0;
			return true;
	}

	return false;
}
Beispiel #6
0
static int describe_instruction_cop0(rsp_state *rsp, UINT32 op, opcode_desc *desc)
{
	switch (RSREG)
	{
		case 0x00:	/* MFCz */
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x04:	/* MTCz */
			desc->regin[0] |= REGFLAG_R(RTREG);
			return TRUE;
	}

	return FALSE;
}
Beispiel #7
0
bool rsp_frontend::describe_cop2(UINT32 op, opcode_desc &desc)
{
	switch (RSREG)
	{
		case 0x00:  // MFCz
		case 0x02:  // CFCz
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x04:  // MTCz
		case 0x06:  // CTCz
			desc.regin[0] |= REGFLAG_R(RTREG);
			return true;
	}

	return false;
}
Beispiel #8
0
bool sh2_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
    switch (opcode & (15<<8))
    {
    case  0<<8: // MOVBSG(opcode & 0xff);
    case  1<<8: // MOVWSG(opcode & 0xff);
    case  2<<8: // MOVLSG(opcode & 0xff);
        desc.regin[0] |= REGFLAG_R(0);
        desc.flags |= OPFLAG_WRITES_MEMORY;
        return true;

    case  3<<8: // TRAPA(opcode & 0xff);
        desc.regin[0] |= REGFLAG_R(15);
        desc.regin[1] |= REGFLAG_VBR;
        desc.regout[0] |= REGFLAG_R(15);
        desc.cycles = 8;
        desc.targetpc = BRANCH_TARGET_DYNAMIC;
        desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
        return true;

    case  4<<8: // MOVBLG(opcode & 0xff);
    case  5<<8: // MOVWLG(opcode & 0xff);
    case  6<<8: // MOVLLG(opcode & 0xff);
    case  7<<8: // MOVA(opcode & 0xff);
        desc.regout[0] |= REGFLAG_R(0);
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;

    case  8<<8: // TSTI(opcode & 0xff);
        desc.regin[0] |= REGFLAG_R(0);
        desc.regin[1] |= REGFLAG_SR;
        desc.regout[1] |= REGFLAG_SR;
        return true;

    case  9<<8: // ANDI(opcode & 0xff);
    case 10<<8: // XORI(opcode & 0xff);
    case 11<<8: // ORI(opcode & 0xff);
        desc.regin[0] |= REGFLAG_R(0);
        desc.regout[0] |= REGFLAG_R(0);
        return true;

    case 12<<8: // TSTM(opcode & 0xff);
    case 13<<8: // ANDM(opcode & 0xff);
    case 14<<8: // XORM(opcode & 0xff);
    case 15<<8: // ORM(opcode & 0xff);
        desc.regin[0] |= REGFLAG_R(0);
        desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR;
        desc.regout[1] |= REGFLAG_SR;
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;
    }

    return false;
}
Beispiel #9
0
static int describe_instruction_idt(mips3_state *mips, UINT32 op, opcode_desc *desc)
{
	switch (op & 0x1f)
	{
		case 0: /* MAD */
		case 1: /* MADU */
			desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG) | REGFLAG_LO | REGFLAG_HI;
			desc->gpr.modified |= REGFLAG_LO | REGFLAG_HI;
			return TRUE;

		case 2: /* MUL */
			desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->gpr.modified |= REGFLAG_R(RDREG);
			desc->cycles = 3;
			return TRUE;
	}

	return FALSE;
}
Beispiel #10
0
bool rsp_frontend::describe_cop0(UINT32 op, opcode_desc &desc)
{
	switch (RSREG)
	{
		case 0x00:  // MFCz
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x04:  // MTCz
			desc.regin[0] |= REGFLAG_R(RTREG);
			if(RDREG == 2) // SP_RD_LEN, initiating DMA
			{
				desc.flags |= OPFLAG_END_SEQUENCE;
			}
			return true;
	}

	return false;
}
Beispiel #11
0
bool sh2_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
    switch (opcode & 15)
    {
    case  0: // MOVBL(Rm, Rn);
    case  1: // MOVWL(Rm, Rn);
    case  2: // MOVLL(Rm, Rn);
    case  3: // MOV(Rm, Rn);
    case  7: // NOT(Rm, Rn);
    case  9: // SWAPW(Rm, Rn);
    case 11: // NEG(Rm, Rn);
    case 12: // EXTUB(Rm, Rn);
    case 13: // EXTUW(Rm, Rn);
    case 14: // EXTSB(Rm, Rn);
    case 15: // EXTSW(Rm, Rn);
        desc.regin[0] |= REGFLAG_R(Rm);
        desc.regout[0] |= REGFLAG_R(Rn);
        return true;

    case  4: // MOVBP(Rm, Rn);
    case  5: // MOVWP(Rm, Rn);
    case  6: // MOVLP(Rm, Rn);
        desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;

    case  8: // SWAPB(Rm, Rn);
        desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        return true;

    case 10: // NEGC(Rm, Rn);
        desc.regin[0] |= REGFLAG_R(Rm);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_SR;
        return true;
    }
    return false;
}
Beispiel #12
0
static int describe_instruction_idt(mips3_state *mipsaa, UINT32 op, opcode_desc *desc)
{
	/* only on the R4650 */
	if (mipsaa->flavor != MIPS3_TYPE_R4650)
		return FALSE;

	switch (op & 0x1f)
	{
		case 0: /* MAD */
		case 1: /* MADU */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regin[2] |= REGFLAG_LO | REGFLAG_HI;
			desc->regout[2] |= REGFLAG_LO | REGFLAG_HI;
			return TRUE;

		case 2: /* MUL */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			desc->cycles = 3;
			return TRUE;
	}

	return FALSE;
}
Beispiel #13
0
static int describe_instruction_cop1x(mips3_state *mipsaa, UINT32 op, opcode_desc *desc)
{
	/* any COP1 instruction can potentially cause an exception */
//  desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;

	switch (op & 0x3f)
	{
		case 0x00:	/* LWXC1 */
		case 0x01:	/* LDXC1 */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[1] |= REGFLAG_CPR1(FDREG);
			desc->flags |= OPFLAG_READS_MEMORY;
			return TRUE;

		case 0x08:	/* SWXC1 */
		case 0x09:	/* SDXC1 */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regin[1] |= REGFLAG_CPR1(FDREG);
			desc->flags |= OPFLAG_WRITES_MEMORY;
			return TRUE;

		case 0x0f:	/* PREFX */
			/* effective no-op */
			return TRUE;

		case 0x20:	case 0x21:	/* MADD */
		case 0x28:	case 0x29:	/* MSUB */
		case 0x30:	case 0x31:	/* NMADD */
		case 0x38:	case 0x39:	/* NMSUB */
			desc->regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG) | REGFLAG_CPR1(FRREG);
			desc->regout[1] |= REGFLAG_CPR1(FDREG);
			return TRUE;
	}

	return FALSE;
}
Beispiel #14
0
static int describe_instruction_regimm(rsp_state *rsp, UINT32 op, opcode_desc *desc)
{
	switch (RTREG)
	{
		case 0x00:	/* BLTZ */
		case 0x01:	/* BGEZ */
			if (RTREG == 0x01 && RSREG == 0)
				desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc->regin[0] |= REGFLAG_R(RSREG);
				desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc->targetpc = ((desc->pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
			desc->delayslots = 1;
			desc->skipslots = (RTREG & 0x02) ? 1 : 0;
			return TRUE;

		case 0x10:	/* BLTZAL */
		case 0x11:	/* BGEZAL */
			if (RTREG == 0x11 && RSREG == 0)
				desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc->regin[0] |= REGFLAG_R(RSREG);
				desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc->regout[0] |= REGFLAG_R(31);
			desc->targetpc = ((desc->pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
			desc->delayslots = 1;
			desc->skipslots = (RTREG & 0x02) ? 1 : 0;
			return TRUE;
	}

	return FALSE;
}
Beispiel #15
0
bool mips3_frontend::describe_cop1x(UINT32 op, opcode_desc &desc)
{
	// any COP1 instruction can potentially cause an exception
//  desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;

	switch (op & 0x3f)
	{
		case 0x00:  // LWXC1
		case 0x01:  // LDXC1
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[1] |= REGFLAG_CPR1(FDREG);
			desc.flags |= OPFLAG_READS_MEMORY;
			return true;

		case 0x08:  // SWXC1
		case 0x09:  // SDXC1
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regin[1] |= REGFLAG_CPR1(FDREG);
			desc.flags |= OPFLAG_WRITES_MEMORY;
			return true;

		case 0x0f:  // PREFX
			// effective no-op
			return true;

		case 0x20:  case 0x21:  // MADD
		case 0x28:  case 0x29:  // MSUB
		case 0x30:  case 0x31:  // NMADD
		case 0x38:  case 0x39:  // NMSUB
			desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG) | REGFLAG_CPR1(FRREG);
			desc.regout[1] |= REGFLAG_CPR1(FDREG);
			return true;
	}

	return false;
}
Beispiel #16
0
bool rsp_frontend::describe_regimm(UINT32 op, opcode_desc &desc)
{
	switch (RTREG)
	{
		case 0x00:  // BLTZ
		case 0x01:  // BGEZ
			if (RTREG == 0x01 && RSREG == 0)
				desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc.regin[0] |= REGFLAG_R(RSREG);
				desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000;
			desc.delayslots = 1;
			desc.skipslots = (RTREG & 0x02) ? 1 : 0;
			return true;

		case 0x10:  // BLTZAL
		case 0x11:  // BGEZAL
			if (RTREG == 0x11 && RSREG == 0)
				desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc.regin[0] |= REGFLAG_R(RSREG);
				desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc.regout[0] |= REGFLAG_R(31);
			desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000;
			desc.delayslots = 1;
			desc.skipslots = (RTREG & 0x02) ? 1 : 0;
			return true;
	}

	return false;
}
Beispiel #17
0
bool mips3_frontend::describe_idt(UINT32 op, opcode_desc &desc)
{
	// only on the R4650
	if (m_context.flavor != MIPS3_TYPE_R4650)
		return false;

	switch (op & 0x1f)
	{
		case 0: // MAD
		case 1: // MADU
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regin[2] |= REGFLAG_LO | REGFLAG_HI;
			desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
			return true;

		case 2: // MUL
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			desc.cycles = 3;
			return true;
	}

	return false;
}
Beispiel #18
0
bool mips3_frontend::describe_cop1(UINT32 op, opcode_desc &desc)
{
	// any COP1 instruction can potentially cause an exception
//  desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;

	switch (RSREG)
	{
		case 0x00:  // MFCz
		case 0x01:  // DMFCz
			desc.regin[1] |= REGFLAG_CPR1(RDREG);
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x02:  // CFCz
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x04:  // MTCz
		case 0x05:  // DMTCz
			desc.regin[0] |= REGFLAG_R(RTREG);
			desc.regout[1] |= REGFLAG_CPR1(RDREG);
			return true;

		case 0x06:  // CTCz
			desc.regin[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x08:  // BC
			switch (RTREG & 3)
			{
				case 0x00:  // BCzF
				case 0x01:  // BCzT
				case 0x02:  // BCzFL
				case 0x03:  // BCzTL
					desc.regin[2] |= REGFLAG_FCC;
					desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
					desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
					desc.delayslots = 1;
					desc.skipslots = (RTREG & 0x02) ? 1 : 0;
					return true;
			}
			return false;

		case 0x10:  case 0x11:  case 0x12:  case 0x13:  case 0x14:  case 0x15:  case 0x16:  case 0x17:
		case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:  // COP
			switch (op & 0x3f)
			{
				case 0x12:  // MOVZ - MIPS IV
				case 0x13:  // MOVN - MIPS IV
					if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
						return false;
				case 0x00:  // ADD
				case 0x01:  // SUB
				case 0x02:  // MUL
				case 0x03:  // DIV
					desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG);
					desc.regout[1] |= REGFLAG_CPR1(FDREG);
					return true;

				case 0x15:  // RECIP - MIPS IV
				case 0x16:  // RSQRT - MIPS IV
					if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
						return false;
				case 0x04:  // SQRT
				case 0x05:  // ABS
				case 0x06:  // MOV
				case 0x07:  // NEG
				case 0x08:  // ROUND.L
				case 0x09:  // TRUNC.L
				case 0x0a:  // CEIL.L
				case 0x0b:  // FLOOR.L
				case 0x0c:  // ROUND.W
				case 0x0d:  // TRUNC.W
				case 0x0e:  // CEIL.W
				case 0x0f:  // FLOOR.W
				case 0x20:  // CVT.S
				case 0x21:  // CVT.D
				case 0x24:  // CVT.W
				case 0x25:  // CVT.L
					desc.regin[1] |= REGFLAG_CPR1(FSREG);
					desc.regout[1] |= REGFLAG_CPR1(FDREG);
					return true;

				case 0x11:  // MOVT/F - MIPS IV
					if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
						return false;
					desc.regin[1] |= REGFLAG_CPR1(FSREG);
					desc.regin[2] |= REGFLAG_FCC;
					desc.regout[1] |= REGFLAG_CPR1(FDREG);
					return true;

				case 0x30:  case 0x38:  // C.F
				case 0x31:  case 0x39:  // C.UN
					desc.regout[2] |= REGFLAG_FCC;
					return true;

				case 0x32:  case 0x3a:  // C.EQ
				case 0x33:  case 0x3b:  // C.UEQ
				case 0x34:  case 0x3c:  // C.OLT
				case 0x35:  case 0x3d:  // C.ULT
				case 0x36:  case 0x3e:  // C.OLE
				case 0x37:  case 0x3f:  // C.ULE
					desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG);
					desc.regout[2] |= REGFLAG_FCC;
					return true;
			}
			return false;
	}

	return false;
}
Beispiel #19
0
static int describe_instruction_special(rsp_state *rsp, UINT32 op, opcode_desc *desc)
{
	switch (op & 63)
	{
		case 0x00:	/* SLL */
		case 0x02:	/* SRL */
		case 0x03:	/* SRA */
			desc->regin[0] |= REGFLAG_R(RTREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			return TRUE;

		case 0x04:	/* SLLV */
		case 0x06:	/* SRLV */
		case 0x07:	/* SRAV */
		case 0x21:	/* ADDU */
		case 0x23:	/* SUBU */
		case 0x24:	/* AND */
		case 0x25:	/* OR */
		case 0x26:	/* XOR */
		case 0x27:	/* NOR */
		case 0x2a:	/* SLT */
		case 0x2b:	/* SLTU */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			return TRUE;

		case 0x20:	/* ADD */
		case 0x22:	/* SUB */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			return TRUE;

		case 0x08:	/* JR */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc->targetpc = BRANCH_TARGET_DYNAMIC;
			desc->delayslots = 1;
			return TRUE;

		case 0x09:	/* JALR */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc->targetpc = BRANCH_TARGET_DYNAMIC;
			desc->delayslots = 1;
			return TRUE;

		case 0x0d:	/* BREAK */
			desc->flags |= OPFLAG_END_SEQUENCE;
			desc->targetpc = BRANCH_TARGET_DYNAMIC;
			return TRUE;
	}

	return FALSE;
}
Beispiel #20
0
bool rsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
{
	UINT32 op, opswitch;

	// fetch the opcode
	op = desc.opptr.l[0] = m_rsp.m_direct->read_decrypted_dword(desc.physpc | 0x1000);

	// all instructions are 4 bytes and default to a single cycle each
	desc.length = 4;
	desc.cycles = 1;

	// parse the instruction
	opswitch = op >> 26;
	switch (opswitch)
	{
		case 0x00:  // SPECIAL
			return describe_special(op, desc);

		case 0x01:  // REGIMM
			return describe_regimm(op, desc);

		case 0x10:  // COP0
			return describe_cop0(op, desc);

		case 0x12:  // COP2
			return describe_cop2(op, desc);

		case 0x02:  // J
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
			desc.delayslots = 1;
			return true;

		case 0x03:  // JAL
			desc.regout[0] |= REGFLAG_R(31);
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
			desc.delayslots = 1;
			return true;

		case 0x04:  // BEQ
		case 0x05:  // BNE
			if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
				desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
				desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000;
			desc.delayslots = 1;
			desc.skipslots = (opswitch & 0x10) ? 1 : 0;
			return true;

		case 0x06:  // BLEZ
		case 0x07:  // BGTZ
			if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
				desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc.regin[0] |= REGFLAG_R(RSREG);
				desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000;
			desc.delayslots = 1;
			desc.skipslots = (opswitch & 0x10) ? 1 : 0;
			return true;

		case 0x08:  // ADDI
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x09:  // ADDIU
		case 0x0a:  // SLTI
		case 0x0b:  // SLTIU
		case 0x0c:  // ANDI
		case 0x0d:  // ORI
		case 0x0e:  // XORI
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x0f:  // LUI
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x20:  // LB
		case 0x21:  // LH
		case 0x23:  // LW
		case 0x24:  // LBU
		case 0x25:  // LHU
		case 0x27:  // LWU
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_R(RTREG);
			desc.flags |= OPFLAG_READS_MEMORY;
			return true;

		case 0x28:  // SB
		case 0x29:  // SH
		case 0x2b:  // SW
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.flags |= OPFLAG_WRITES_MEMORY;
			return true;

		case 0x32:  // LWC2
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.flags |= OPFLAG_READS_MEMORY;
			return true;

		case 0x3a:  // SWC2
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.flags |= OPFLAG_WRITES_MEMORY;
			return true;
	}

	return false;
}
Beispiel #21
0
static int describe_instruction_special(mips3_state *mipsaa, UINT32 op, opcode_desc *desc)
{
	switch (op & 63)
	{
		case 0x00:	/* SLL */
		case 0x02:	/* SRL */
		case 0x03:	/* SRA */
		case 0x38:	/* DSLL */
		case 0x3a:	/* DSRL */
		case 0x3b:	/* DSRA */
		case 0x3c:	/* DSLL32 */
		case 0x3e:	/* DSRL32 */
		case 0x3f:	/* DSRA32 */
			desc->regin[0] |= REGFLAG_R(RTREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			return TRUE;

		case 0x0a:	/* MOVZ - MIPS IV */
		case 0x0b:	/* MOVN - MIPS IV */
			if (mipsaa->flavor < MIPS3_TYPE_MIPS_IV)
				return FALSE;
			desc->regin[0] |= REGFLAG_R(RDREG);
		case 0x04:	/* SLLV */
		case 0x06:	/* SRLV */
		case 0x07:	/* SRAV */
		case 0x14:	/* DSLLV */
		case 0x16:	/* DSRLV */
		case 0x17:	/* DSRAV */
		case 0x21:	/* ADDU */
		case 0x23:	/* SUBU */
		case 0x24:	/* AND */
		case 0x25:	/* OR */
		case 0x26:	/* XOR */
		case 0x27:	/* NOR */
		case 0x2a:	/* SLT */
		case 0x2b:	/* SLTU */
		case 0x2d:	/* DADDU */
		case 0x2f:	/* DSUBU */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			return TRUE;

		case 0x20:	/* ADD */
		case 0x22:	/* SUB */
		case 0x2c:	/* DADD */
		case 0x2e:	/* DSUB */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x30:	/* TGE */
		case 0x31:	/* TGEU */
		case 0x32:	/* TLT */
		case 0x33:	/* TLTU */
		case 0x34:	/* TEQ */
		case 0x36:	/* TNE */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x01:	/* MOVF - MIPS IV */
			if (mipsaa->flavor < MIPS3_TYPE_MIPS_IV)
				return FALSE;
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regin[2] |= REGFLAG_FCC;
			desc->regout[0] |= REGFLAG_R(RDREG);
			return TRUE;

		case 0x08:	/* JR */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc->targetpc = BRANCH_TARGET_DYNAMIC;
			desc->delayslots = 1;
			return TRUE;

		case 0x09:	/* JALR */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_R(RDREG);
			desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc->targetpc = BRANCH_TARGET_DYNAMIC;
			desc->delayslots = 1;
			return TRUE;

		case 0x10:	/* MFHI */
			desc->regin[0] |= REGFLAG_HI;
			desc->regout[0] |= REGFLAG_R(RDREG);
			return TRUE;

		case 0x11:	/* MTHI */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_HI;
			return TRUE;

		case 0x12:	/* MFLO */
			desc->regin[2] |= REGFLAG_LO;
			desc->regout[0] |= REGFLAG_R(RDREG);
			return TRUE;

		case 0x13:	/* MTLO */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[2] |= REGFLAG_LO;
			return TRUE;

		case 0x18:	/* MULT */
		case 0x19:	/* MULTU */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[2] |= REGFLAG_LO | REGFLAG_HI;
			desc->cycles = 3;
			return TRUE;

		case 0x1a:	/* DIV */
		case 0x1b:	/* DIVU */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[2] |= REGFLAG_LO | REGFLAG_HI;
			desc->cycles = 35;
			return TRUE;

		case 0x1c:	/* DMULT */
		case 0x1d:	/* DMULTU */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[2] |= REGFLAG_LO | REGFLAG_HI;
			desc->cycles = 7;
			return TRUE;

		case 0x1e:	/* DDIV */
		case 0x1f:	/* DDIVU */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[2] |= REGFLAG_LO | REGFLAG_HI;
			desc->cycles = 67;
			return TRUE;

		case 0x0c:	/* SYSCALL */
		case 0x0d:	/* BREAK */
			desc->flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE;
			return TRUE;

		case 0x0f:	/* SYNC */
			/* effective no-op */
			return TRUE;
	}

	return FALSE;
}
Beispiel #22
0
bool mips3_frontend::describe_special(UINT32 op, opcode_desc &desc)
{
	switch (op & 63)
	{
		case 0x00:  // SLL
		case 0x02:  // SRL
		case 0x03:  // SRA
		case 0x38:  // DSLL
		case 0x3a:  // DSRL
		case 0x3b:  // DSRA
		case 0x3c:  // DSLL32
		case 0x3e:  // DSRL32
		case 0x3f:  // DSRA32
			desc.regin[0] |= REGFLAG_R(RTREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			return true;

		case 0x0a:  // MOVZ - MIPS IV
		case 0x0b:  // MOVN - MIPS IV
			if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
				return false;
			desc.regin[0] |= REGFLAG_R(RDREG);
		case 0x04:  // SLLV
		case 0x06:  // SRLV
		case 0x07:  // SRAV
		case 0x14:  // DSLLV
		case 0x16:  // DSRLV
		case 0x17:  // DSRAV
		case 0x21:  // ADDU
		case 0x23:  // SUBU
		case 0x24:  // AND
		case 0x25:  // OR
		case 0x26:  // XOR
		case 0x27:  // NOR
		case 0x2a:  // SLT
		case 0x2b:  // SLTU
		case 0x2d:  // DADDU
		case 0x2f:  // DSUBU
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			return true;

		case 0x20:  // ADD
		case 0x22:  // SUB
		case 0x2c:  // DADD
		case 0x2e:  // DSUB
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x30:  // TGE
		case 0x31:  // TGEU
		case 0x32:  // TLT
		case 0x33:  // TLTU
		case 0x34:  // TEQ
		case 0x36:  // TNE
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x01:  // MOVF - MIPS IV
			if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
				return false;
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regin[2] |= REGFLAG_FCC;
			desc.regout[0] |= REGFLAG_R(RDREG);
			return true;

		case 0x08:  // JR
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = BRANCH_TARGET_DYNAMIC;
			desc.delayslots = 1;
			return true;

		case 0x09:  // JALR
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = BRANCH_TARGET_DYNAMIC;
			desc.delayslots = 1;
			return true;

		case 0x10:  // MFHI
			desc.regin[0] |= REGFLAG_HI;
			desc.regout[0] |= REGFLAG_R(RDREG);
			return true;

		case 0x11:  // MTHI
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_HI;
			return true;

		case 0x12:  // MFLO
			desc.regin[2] |= REGFLAG_LO;
			desc.regout[0] |= REGFLAG_R(RDREG);
			return true;

		case 0x13:  // MTLO
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[2] |= REGFLAG_LO;
			return true;

		case 0x18:  // MULT
		case 0x19:  // MULTU
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
			desc.cycles = 3;
			return true;

		case 0x1a:  // DIV
		case 0x1b:  // DIVU
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
			desc.cycles = 35;
			return true;

		case 0x1c:  // DMULT
		case 0x1d:  // DMULTU
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
			desc.cycles = 7;
			return true;

		case 0x1e:  // DDIV
		case 0x1f:  // DDIVU
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
			desc.cycles = 67;
			return true;

		case 0x0c:  // SYSCALL
		case 0x0d:  // BREAK
			desc.flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE;
			return true;

		case 0x0f:  // SYNC
			// effective no-op
			return true;
	}

	return false;
}
Beispiel #23
0
bool rsp_frontend::describe_special(UINT32 op, opcode_desc &desc)
{
	switch (op & 63)
	{
		case 0x00:  // SLL
		case 0x02:  // SRL
		case 0x03:  // SRA
			desc.regin[0] |= REGFLAG_R(RTREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			return true;

		case 0x04:  // SLLV
		case 0x06:  // SRLV
		case 0x07:  // SRAV
		case 0x21:  // ADDU
		case 0x23:  // SUBU
		case 0x24:  // AND
		case 0x25:  // OR
		case 0x26:  // XOR
		case 0x27:  // NOR
		case 0x2a:  // SLT
		case 0x2b:  // SLTU
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			return true;

		case 0x20:  // ADD
		case 0x22:  // SUB
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			return true;

		case 0x08:  // JR
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = BRANCH_TARGET_DYNAMIC;
			desc.delayslots = 1;
			return true;

		case 0x09:  // JALR
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_R(RDREG);
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = BRANCH_TARGET_DYNAMIC;
			desc.delayslots = 1;
			return true;

		case 0x0d:  // BREAK
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = (op >> 5) & 0x000fffff;
			return true;
	}

	return false;
}
Beispiel #24
0
int mips3fe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
{
	mips3_state *mipsaa = (mips3_state *)param;
	UINT32 op, opswitch;

	/* compute the physical PC */
	if (!mips3com_translate_address(mipsaa, ADDRESS_SPACE_PROGRAM, TRANSLATE_FETCH, &desc->physpc))
	{
		/* uh-oh: a page fault; leave the description empty and just if this is the first instruction, leave it empty and */
		/* mark as needing to validate; otherwise, just end the sequence here */
		desc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_COMPILER_PAGE_FAULT | OPFLAG_VIRTUAL_NOOP | OPFLAG_END_SEQUENCE;
		return TRUE;
	}

	/* fetch the opcode */
	op = desc->opptr.l[0] = memory_decrypted_read_dword(mipsaa->program, desc->physpc);

	/* all instructions are 4 bytes and default to a single cycle each */
	desc->length = 4;
	desc->cycles = 1;

	/* parse the instruction */
	opswitch = op >> 26;
	switch (opswitch)
	{
		case 0x00:	/* SPECIAL */
			return describe_instruction_special(mipsaa, op, desc);

		case 0x01:	/* REGIMM */
			return describe_instruction_regimm(mipsaa, op, desc);

		case 0x10:	/* COP0 */
			return describe_instruction_cop0(mipsaa, op, desc);

		case 0x11:	/* COP1 */
			return describe_instruction_cop1(mipsaa, op, desc);

		case 0x12:	/* COP2 */
			return describe_instruction_cop2(mipsaa, op, desc);

		case 0x13:	/* COP1X - MIPS IV */
			if (mipsaa->flavor < MIPS3_TYPE_MIPS_IV)
				return FALSE;
			return describe_instruction_cop1x(mipsaa, op, desc);

		case 0x1c:	/* IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364 */
			return describe_instruction_idt(mipsaa, op, desc);

		case 0x02:	/* J */
			desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc->targetpc = (desc->pc & 0xf0000000) | (LIMMVAL << 2);
			desc->delayslots = 1;
			return TRUE;

		case 0x03:	/* JAL */
			desc->regout[0] |= REGFLAG_R(31);
			desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc->targetpc = (desc->pc & 0xf0000000) | (LIMMVAL << 2);
			desc->delayslots = 1;
			return TRUE;

		case 0x04:	/* BEQ */
		case 0x05:	/* BNE */
		case 0x14:	/* BEQL */
		case 0x15:	/* BNEL */
			if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
				desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
				desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
			desc->delayslots = 1;
			desc->skipslots = (opswitch & 0x10) ? 1 : 0;
			return TRUE;

		case 0x06:	/* BLEZ */
		case 0x07:	/* BGTZ */
		case 0x16:	/* BLEZL */
		case 0x17:	/* BGTZL */
			if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
				desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc->regin[0] |= REGFLAG_R(RSREG);
				desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
			desc->delayslots = 1;
			desc->skipslots = (opswitch & 0x10) ? 1 : 0;
			return TRUE;

		case 0x08:	/* ADDI */
		case 0x18:	/* DADDI */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_R(RTREG);
			desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x09:	/* ADDIU */
		case 0x0a:	/* SLTI */
		case 0x0b:	/* SLTIU */
		case 0x0c:	/* ANDI */
		case 0x0d:	/* ORI */
		case 0x0e:	/* XORI */
		case 0x19:	/* DADDIU */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x0f:	/* LUI */
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x1a:	/* LDL */
		case 0x1b:	/* LDR */
		case 0x22:	/* LWL */
		case 0x26:	/* LWR */
			desc->regin[0] |= REGFLAG_R(RTREG);
		case 0x20:	/* LB */
		case 0x21:	/* LH */
		case 0x23:	/* LW */
		case 0x24:	/* LBU */
		case 0x25:	/* LHU */
		case 0x27:	/* LWU */
		case 0x30:	/* LL */
		case 0x34:	/* LLD */
		case 0x37:	/* LD */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_R(RTREG);
			desc->flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x28:	/* SB */
		case 0x29:	/* SH */
		case 0x2a:	/* SWL */
		case 0x2b:	/* SW */
		case 0x2c:	/* SDL */
		case 0x2d:	/* SDR */
		case 0x2e:	/* SWR */
		case 0x3f:	/* SD */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x38:	/* SC */
		case 0x3c:	/* SCD */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->regout[0] |= REGFLAG_R(RTREG);
			desc->flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x31:	/* LWC1 */
		case 0x35:	/* LDC1 */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[1] |= REGFLAG_CPR1(RTREG);
			desc->flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x39:	/* SWC1 */
		case 0x3d:	/* SDC1 */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regin[1] |= REGFLAG_CPR1(RTREG);
			desc->flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x32:	/* LWC2 */
		case 0x36:	/* LDC2 */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x3a:	/* SWC2 */
		case 0x3e:	/* SDC2 */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x33:	/* PREF */
			if (mipsaa->flavor < MIPS3_TYPE_MIPS_IV)
				return FALSE;
		case 0x2f:	/* CACHE */
			/* effective no-op */
			return TRUE;
	}

	return FALSE;
}
Beispiel #25
0
static int describe_instruction_cop1(mips3_state *mipsaa, UINT32 op, opcode_desc *desc)
{
	/* any COP1 instruction can potentially cause an exception */
//  desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;

	switch (RSREG)
	{
		case 0x00:	/* MFCz */
		case 0x01:	/* DMFCz */
			desc->regin[1] |= REGFLAG_CPR1(RDREG);
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x02:	/* CFCz */
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x04:	/* MTCz */
		case 0x05:	/* DMTCz */
			desc->regin[0] |= REGFLAG_R(RTREG);
			desc->regout[1] |= REGFLAG_CPR1(RDREG);
			return TRUE;

		case 0x06:	/* CTCz */
			desc->regin[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x08:	/* BC */
			switch (RTREG & 3)
			{
				case 0x00:	/* BCzF */
				case 0x01:	/* BCzT */
				case 0x02:	/* BCzFL */
				case 0x03:	/* BCzTL */
					desc->regin[2] |= REGFLAG_FCC;
					desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
					desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
					desc->delayslots = 1;
					desc->skipslots = (RTREG & 0x02) ? 1 : 0;
					return TRUE;
			}
			return FALSE;

		case 0x10:	case 0x11:	case 0x12:	case 0x13:	case 0x14:	case 0x15:	case 0x16:	case 0x17:
		case 0x18:	case 0x19:	case 0x1a:	case 0x1b:	case 0x1c:	case 0x1d:	case 0x1e:	case 0x1f:	/* COP */
			switch (op & 0x3f)
			{
				case 0x12:	/* MOVZ - MIPS IV */
				case 0x13:	/* MOVN - MIPS IV */
					if (mipsaa->flavor < MIPS3_TYPE_MIPS_IV)
						return FALSE;
				case 0x00:	/* ADD */
				case 0x01:	/* SUB */
				case 0x02:	/* MUL */
				case 0x03:	/* DIV */
					desc->regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG);
					desc->regout[1] |= REGFLAG_CPR1(FDREG);
					return TRUE;

				case 0x15:	/* RECIP - MIPS IV */
				case 0x16:	/* RSQRT - MIPS IV */
					if (mipsaa->flavor < MIPS3_TYPE_MIPS_IV)
						return FALSE;
				case 0x04:	/* SQRT */
				case 0x05:	/* ABS */
				case 0x06:	/* MOV */
				case 0x07:	/* NEG */
				case 0x08:	/* ROUND.L */
				case 0x09:	/* TRUNC.L */
				case 0x0a:	/* CEIL.L */
				case 0x0b:	/* FLOOR.L */
				case 0x0c:	/* ROUND.W */
				case 0x0d:	/* TRUNC.W */
				case 0x0e:	/* CEIL.W */
				case 0x0f:	/* FLOOR.W */
				case 0x20:	/* CVT.S */
				case 0x21:	/* CVT.D */
				case 0x24:	/* CVT.W */
				case 0x25:	/* CVT.L */
					desc->regin[1] |= REGFLAG_CPR1(FSREG);
					desc->regout[1] |= REGFLAG_CPR1(FDREG);
					return TRUE;

				case 0x11:	/* MOVT/F - MIPS IV */
					if (mipsaa->flavor < MIPS3_TYPE_MIPS_IV)
						return FALSE;
					desc->regin[1] |= REGFLAG_CPR1(FSREG);
					desc->regin[2] |= REGFLAG_FCC;
					desc->regout[1] |= REGFLAG_CPR1(FDREG);
					return TRUE;

				case 0x30:	case 0x38:	/* C.F */
				case 0x31:	case 0x39:	/* C.UN */
					desc->regout[2] |= REGFLAG_FCC;
					return TRUE;

				case 0x32:	case 0x3a:	/* C.EQ */
				case 0x33:	case 0x3b:	/* C.UEQ */
				case 0x34:	case 0x3c:	/* C.OLT */
				case 0x35:	case 0x3d:	/* C.ULT */
				case 0x36:	case 0x3e:	/* C.OLE */
				case 0x37:	case 0x3f:	/* C.ULE */
					desc->regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG);
					desc->regout[2] |= REGFLAG_FCC;
					return TRUE;
			}
			return FALSE;
	}

	return FALSE;
}
Beispiel #26
0
bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
{
	UINT32 op, opswitch;

	// compute the physical PC
	assert((desc.physpc & 3) == 0);
	if (!mips3com_translate_address(&m_context, AS_PROGRAM, TRANSLATE_FETCH, &desc.physpc))
	{
		// uh-oh: a page fault; leave the description empty and just if this is the first instruction, leave it empty and
		// mark as needing to validate; otherwise, just end the sequence here
		desc.flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_COMPILER_PAGE_FAULT | OPFLAG_VIRTUAL_NOOP | OPFLAG_END_SEQUENCE;
		return true;
	}

	// fetch the opcode
	assert((desc.physpc & 3) == 0);
	op = desc.opptr.l[0] = m_context.direct->read_decrypted_dword(desc.physpc);

	// all instructions are 4 bytes and default to a single cycle each
	desc.length = 4;
	desc.cycles = 1;

	// parse the instruction
	opswitch = op >> 26;
	switch (opswitch)
	{
		case 0x00:  // SPECIAL
			return describe_special(op, desc);

		case 0x01:  // REGIMM
			return describe_regimm(op, desc);

		case 0x10:  // COP0
			return describe_cop0(op, desc);

		case 0x11:  // COP1
			return describe_cop1(op, desc);

		case 0x12:  // COP2
			return describe_cop2(op, desc);

		case 0x13:  // COP1X - MIPS IV
			if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
				return false;
			return describe_cop1x(op, desc);

		case 0x1c:  // IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364
			return describe_idt(op, desc);

		case 0x02:  // J
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = (desc.pc & 0xf0000000) | (LIMMVAL << 2);
			desc.delayslots = 1;
			return true;

		case 0x03:  // JAL
			desc.regout[0] |= REGFLAG_R(31);
			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc.targetpc = (desc.pc & 0xf0000000) | (LIMMVAL << 2);
			desc.delayslots = 1;
			return true;

		case 0x04:  // BEQ
		case 0x05:  // BNE
		case 0x14:  // BEQL
		case 0x15:  // BNEL
			if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
				desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
				desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
			desc.delayslots = 1;
			desc.skipslots = (opswitch & 0x10) ? 1 : 0;
			return true;

		case 0x06:  // BLEZ
		case 0x07:  // BGTZ
		case 0x16:  // BLEZL
		case 0x17:  // BGTZL
			if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
				desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc.regin[0] |= REGFLAG_R(RSREG);
				desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
			desc.delayslots = 1;
			desc.skipslots = (opswitch & 0x10) ? 1 : 0;
			return true;

		case 0x08:  // ADDI
		case 0x18:  // DADDI
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_R(RTREG);
			desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x09:  // ADDIU
		case 0x0a:  // SLTI
		case 0x0b:  // SLTIU
		case 0x0c:  // ANDI
		case 0x0d:  // ORI
		case 0x0e:  // XORI
		case 0x19:  // DADDIU
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x0f:  // LUI
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x1a:  // LDL
		case 0x1b:  // LDR
		case 0x22:  // LWL
		case 0x26:  // LWR
			desc.regin[0] |= REGFLAG_R(RTREG);
		case 0x20:  // LB
		case 0x21:  // LH
		case 0x23:  // LW
		case 0x24:  // LBU
		case 0x25:  // LHU
		case 0x27:  // LWU
		case 0x30:  // LL
		case 0x34:  // LLD
		case 0x37:  // LD
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[0] |= REGFLAG_R(RTREG);
			desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x28:  // SB
		case 0x29:  // SH
		case 0x2a:  // SWL
		case 0x2b:  // SW
		case 0x2c:  // SDL
		case 0x2d:  // SDR
		case 0x2e:  // SWR
		case 0x3f:  // SD
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x38:  // SC
		case 0x3c:  // SCD
			desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc.regout[0] |= REGFLAG_R(RTREG);
			desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x31:  // LWC1
		case 0x35:  // LDC1
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regout[1] |= REGFLAG_CPR1(RTREG);
			desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x39:  // SWC1
		case 0x3d:  // SDC1
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.regin[1] |= REGFLAG_CPR1(RTREG);
			desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x32:  // LWC2
		case 0x36:  // LDC2
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x3a:  // SWC2
		case 0x3e:  // SDC2
			desc.regin[0] |= REGFLAG_R(RSREG);
			desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return true;

		case 0x33:  // PREF
			if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
				return false;
		case 0x2f:  // CACHE
			// effective no-op
			return true;
	}

	return false;
}
Beispiel #27
0
bool mips3_frontend::describe_cop0(UINT32 op, opcode_desc &desc)
{
	// any COP0 instruction can potentially cause an exception
	desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;

	switch (RSREG)
	{
		case 0x00:  // MFCz
		case 0x01:  // DMFCz
			if (RDREG == COP0_Count)
				desc.cycles += MIPS3_COUNT_READ_CYCLES;
			if (RDREG == COP0_Cause)
				desc.cycles += MIPS3_CAUSE_READ_CYCLES;
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x02:  // CFCz
			desc.regout[0] |= REGFLAG_R(RTREG);
			return true;

		case 0x04:  // MTCz
		case 0x05:  // DMTCz
		case 0x06:  // CTCz
			desc.regin[0] |= REGFLAG_R(RTREG);
			if (RSREG == 0x04 || RSREG == 0x05)
			{
				if (RDREG == COP0_Cause)
					desc.flags |= OPFLAG_CAN_TRIGGER_SW_INT;
				if (RDREG == COP0_Status)
					desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
			}
			return true;

		case 0x08:  // BC
			switch (RTREG)
			{
				case 0x00:  // BCzF
				case 0x01:  // BCzT
					desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
					desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
					desc.delayslots = 1;
					return true;
			}
			return false;

		case 0x10:  case 0x11:  case 0x12:  case 0x13:  case 0x14:  case 0x15:  case 0x16:  case 0x17:
		case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:  // COP
			switch (op & 0x01ffffff)
			{
				case 0x01:  // TLBR
				case 0x08:  // TLBP
				case 0x20:  // WAIT
					return true;

				case 0x02:  // TLBWI
				case 0x06:  // TLBWR
					desc.flags |= OPFLAG_MODIFIES_TRANSLATION;
					return true;

				case 0x18:  // ERET
					desc.flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
					return true;
			}
			return false;
	}

	return false;
}
Beispiel #28
0
bool sh2_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
{
    switch (opcode & 0x3F)
    {
    case 0x00: // SHLL(Rn);
    case 0x01: // SHLR(Rn);
    case 0x04: // ROTL(Rn);
    case 0x05: // ROTR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_SR;
        return true;

    case 0x02: // STSMMACH(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_MACH;
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.flags |= OPFLAG_WRITES_MEMORY;
        return true;

    case 0x03: // STCMSR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.cycles = 2;
        desc.flags |= OPFLAG_WRITES_MEMORY;
        return true;

    case 0x06: // LDSMMACH(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_MACH;
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;

    case 0x07: // LDCMSR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_SR;
        desc.cycles = 3;
        desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
        return true;

    case 0x08: // SHLL2(Rn);
    case 0x09: // SHLR2(Rn);
    case 0x18: // SHLL8(Rn);
    case 0x19: // SHLR8(Rn);
    case 0x28: // SHLL16(Rn);
    case 0x29: // SHLR16(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        return true;

    case 0x0a: // LDSMACH(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_MACH;
        return true;

    case 0x0b: // JSR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_PR;
        desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
        desc.targetpc = BRANCH_TARGET_DYNAMIC;
        desc.delayslots = 1;
        return true;

    case 0x0e: // LDCSR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_SR;
        desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
        return true;

    case 0x0f: // MAC_W(Rm, Rn);
    case 0x1f: // MAC_W(Rm, Rn);
    case 0x2f: // MAC_W(Rm, Rn);
    case 0x3f: // MAC_W(Rm, Rn);
        desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_MACL | REGFLAG_MACH;
        desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
        desc.cycles = 3;
        return true;

    case 0x10: // DT(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_SR;
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_SR;
        return true;

    case 0x11: // CMPPZ(Rn);
    case 0x15: // CMPPL(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_SR;
        desc.regout[1] |= REGFLAG_SR;
        return true;

    case 0x12: // STSMMACL(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_MACL;
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.flags |= OPFLAG_WRITES_MEMORY;
        return true;

    case 0x13: // STCMGBR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_GBR;
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.flags |= OPFLAG_WRITES_MEMORY;
        return true;

    case 0x16: // LDSMMACL(Rn);
        desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_MACL;
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;

    case 0x17: // LDCMGBR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_GBR;
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;

    case 0x1a: // LDSMACL(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_MACL;
        return true;

    case 0x1b: // TAS(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_SR;
        desc.regout[1] |= REGFLAG_SR;
        desc.cycles = 4;
        desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY;
        return true;

    case 0x1e: // LDCGBR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_GBR;
        return true;

    case 0x20: // SHAL(Rn);
    case 0x21: // SHAR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_SR;
        return true;

    case 0x22: // STSMPR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_PR;
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.flags |= OPFLAG_WRITES_MEMORY;
        return true;

    case 0x23: // STCMVBR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_VBR;
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.flags |= OPFLAG_WRITES_MEMORY;
        return true;

    case 0x24: // ROTCL(Rn);
    case 0x25: // ROTCR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regin[1] |= REGFLAG_SR;
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_SR;
        return true;

    case 0x26: // LDSMPR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_PR;
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;

    case 0x27: // LDCMVBR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_VBR;
        desc.flags |= OPFLAG_READS_MEMORY;
        return true;

    case 0x2a: // LDSPR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_PR;
        return true;

    case 0x2b: // JMP(Rm);
        desc.regin[0] |= REGFLAG_R(Rm);
        desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
        desc.targetpc = BRANCH_TARGET_DYNAMIC;
        desc.delayslots = 1;
        return true;

    case 0x2e: // LDCVBR(Rn);
        desc.regin[0] |= REGFLAG_R(Rn);
        desc.regout[1] |= REGFLAG_VBR;
        return true;

    case 0x0c: // NOP();
    case 0x0d: // NOP();
    case 0x14: // NOP();
    case 0x1c: // NOP();
    case 0x1d: // NOP();
    case 0x2c: // NOP();
    case 0x2d: // NOP();
    case 0x30: // NOP();
    case 0x31: // NOP();
    case 0x32: // NOP();
    case 0x33: // NOP();
    case 0x34: // NOP();
    case 0x35: // NOP();
    case 0x36: // NOP();
    case 0x37: // NOP();
    case 0x38: // NOP();
    case 0x39: // NOP();
    case 0x3a: // NOP();
    case 0x3b: // NOP();
    case 0x3c: // NOP();
    case 0x3d: // NOP();
    case 0x3e: // NOP();
        return true;
    }

    return false;
}
Beispiel #29
0
int rspfe_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
{
	rsp_state *rsp = (rsp_state *)param;
	UINT32 op, opswitch;

	/* fetch the opcode */
	op = desc->opptr.l[0] = memory_decrypted_read_dword(rsp->program, desc->physpc | 0x1000);

	/* all instructions are 4 bytes and default to a single cycle each */
	desc->length = 4;
	desc->cycles = 1;

	/* parse the instruction */
	opswitch = op >> 26;
	switch (opswitch)
	{
		case 0x00:	/* SPECIAL */
			return describe_instruction_special(rsp, op, desc);

		case 0x01:	/* REGIMM */
			return describe_instruction_regimm(rsp, op, desc);

		case 0x10:	/* COP0 */
			return describe_instruction_cop0(rsp, op, desc);

		case 0x12:	/* COP2 */
			return describe_instruction_cop2(rsp, op, desc);

		case 0x02:	/* J */
			desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc->targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
			desc->delayslots = 1;
			return TRUE;

		case 0x03:	/* JAL */
			desc->regout[0] |= REGFLAG_R(31);
			desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			desc->targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
			desc->delayslots = 1;
			return TRUE;

		case 0x04:	/* BEQ */
		case 0x05:	/* BNE */
			if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
				desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
				desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc->targetpc = ((desc->pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
			desc->delayslots = 1;
			desc->skipslots = (opswitch & 0x10) ? 1 : 0;
			return TRUE;

		case 0x06:	/* BLEZ */
		case 0x07:	/* BGTZ */
			if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
				desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
			else
			{
				desc->regin[0] |= REGFLAG_R(RSREG);
				desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
			}
			desc->targetpc = ((desc->pc + 4 + (SIMMVAL << 2)) & 0x00000fff) | 0x1000;
			desc->delayslots = 1;
			desc->skipslots = (opswitch & 0x10) ? 1 : 0;
			return TRUE;

		case 0x08:	/* ADDI */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x09:	/* ADDIU */
		case 0x0a:	/* SLTI */
		case 0x0b:	/* SLTIU */
		case 0x0c:	/* ANDI */
		case 0x0d:	/* ORI */
		case 0x0e:	/* XORI */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x0f:	/* LUI */
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x20:	/* LB */
		case 0x21:	/* LH */
		case 0x23:	/* LW */
		case 0x24:	/* LBU */
		case 0x25:	/* LHU */
		case 0x27:	/* LWU */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->regout[0] |= REGFLAG_R(RTREG);
			desc->flags |= OPFLAG_READS_MEMORY;
			return TRUE;

		case 0x28:	/* SB */
		case 0x29:	/* SH */
		case 0x2b:	/* SW */
			desc->regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->flags |= OPFLAG_WRITES_MEMORY;
			return TRUE;

		case 0x32:	/* LWC2 */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->flags |= OPFLAG_READS_MEMORY;
			return TRUE;

		case 0x3a:	/* SWC2 */
			desc->regin[0] |= REGFLAG_R(RSREG);
			desc->flags |= OPFLAG_WRITES_MEMORY;
			return TRUE;
	}

	return FALSE;
}
Beispiel #30
0
static int describe_instruction_cop0(mips3_state *mipsaa, UINT32 op, opcode_desc *desc)
{
	/* any COP0 instruction can potentially cause an exception */
	desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;

	switch (RSREG)
	{
		case 0x00:	/* MFCz */
		case 0x01:	/* DMFCz */
			if (RDREG == COP0_Count)
				desc->cycles += MIPS3_COUNT_READ_CYCLES;
			if (RDREG == COP0_Cause)
				desc->cycles += MIPS3_CAUSE_READ_CYCLES;
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x02:	/* CFCz */
			desc->regout[0] |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x04:	/* MTCz */
		case 0x05:	/* DMTCz */
		case 0x06:	/* CTCz */
			desc->regin[0] |= REGFLAG_R(RTREG);
			if (RSREG == 0x04 || RSREG == 0x05)
			{
				if (RDREG == COP0_Cause)
					desc->flags |= OPFLAG_CAN_TRIGGER_SW_INT;
				if (RDREG == COP0_Status)
					desc->flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
			}
			return TRUE;

		case 0x08:	/* BC */
			switch (RTREG)
			{
				case 0x00:	/* BCzF */
				case 0x01:	/* BCzT */
					desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
					desc->targetpc = desc->pc + 4 + (SIMMVAL << 2);
					desc->delayslots = 1;
					return TRUE;
			}
			return FALSE;

		case 0x10:	case 0x11:	case 0x12:	case 0x13:	case 0x14:	case 0x15:	case 0x16:	case 0x17:
		case 0x18:	case 0x19:	case 0x1a:	case 0x1b:	case 0x1c:	case 0x1d:	case 0x1e:	case 0x1f:	/* COP */
			switch (op & 0x01ffffff)
			{
				case 0x01:	/* TLBR */
				case 0x08:	/* TLBP */
				case 0x20:	/* WAIT */
					return TRUE;

				case 0x02:	/* TLBWI */
				case 0x06:	/* TLBWR */
					desc->flags |= OPFLAG_MODIFIES_TRANSLATION;
					return TRUE;

				case 0x18:	/* ERET */
					desc->flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
					return TRUE;
			}
			return FALSE;
	}

	return FALSE;
}