Example #1
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;
}
Example #2
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;
}
Example #3
0
int mips3fe_describe(void *param, opcode_desc *desc)
{
	mips3_state *mips = param;
	UINT32 op = *desc->opptr.l;
	UINT8 opswitch = op >> 26;

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

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

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

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

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

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

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

		case 0x1c:	/* IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364 */
			return describe_instruction_idt(mips, 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->gpr.modified |= 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->gpr.used |= 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->gpr.used |= 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->gpr.used |= REGFLAG_R(RSREG);
			desc->gpr.modified |= 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->gpr.used |= REGFLAG_R(RSREG);
			desc->gpr.modified |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x0f:	/* LUI */
			desc->gpr.modified |= REGFLAG_R(RTREG);
			return TRUE;

		case 0x1a:	/* LDL */
		case 0x1b:	/* LDR */
		case 0x22:	/* LWL */
		case 0x26:	/* LWR */
			desc->gpr.used |= 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->gpr.used |= REGFLAG_R(RSREG);
			desc->gpr.modified |= 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 0x38:	/* SC */
		case 0x3c:	/* SCD */
		case 0x3f:	/* SD */
			desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
			desc->flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x31:	/* LWC1 */
		case 0x35:	/* LDC1 */
			desc->gpr.used |= REGFLAG_R(RSREG);
			desc->fpr.modified |= REGFLAG_CPR1(RTREG);
			desc->flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

		case 0x39:	/* SWC1 */
		case 0x3d:	/* SDC1 */
			desc->gpr.used |= REGFLAG_R(RSREG);
			desc->fpr.used |= REGFLAG_CPR1(RTREG);
			desc->flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
			return TRUE;

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

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

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

	return FALSE;
}