Example #1
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;
}
Example #2
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;
}