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; }
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; }
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; }