/*************************************************************************** mips3fe.c Front-end for MIPS3 recompiler Copyright Aaron Giles Released for general use under the MAME license Visit http://mamedev.org for licensing and usage restrictions. ***************************************************************************/ #include #include "cpuintrf.h" #include "mips3fe.h" #include "mips3com.h" /*************************************************************************** FUNCTION PROTOTYPES ***************************************************************************/ static int describe_instruction_special(mips3_state *mips, UINT32 op, opcode_desc *desc); static int describe_instruction_regimm(mips3_state *mips, UINT32 op, opcode_desc *desc); static int describe_instruction_idt(mips3_state *mips, UINT32 op, opcode_desc *desc); static int describe_instruction_cop0(mips3_state *mips, UINT32 op, opcode_desc *desc); static int describe_instruction_cop1(mips3_state *mips, UINT32 op, opcode_desc *desc); static int describe_instruction_cop1x(mips3_state *mips, UINT32 op, opcode_desc *desc); static int describe_instruction_cop2(mips3_state *mips, UINT32 op, opcode_desc *desc); /*************************************************************************** INSTRUCTION PARSERS ***************************************************************************/ /*------------------------------------------------- describe_instruction - build a description of a single instruction -------------------------------------------------*/ 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; } /*------------------------------------------------- describe_instruction_special - build a description of a single instruction in the 'special' group -------------------------------------------------*/ static int describe_instruction_special(mips3_state *mips, 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->gpr.used |= REGFLAG_R(RTREG); desc->gpr.modified |= REGFLAG_R(RDREG); return TRUE; case 0x0a: /* MOVZ - MIPS IV */ case 0x0b: /* MOVN - MIPS IV */ if (mips->flavor < MIPS3_TYPE_MIPS_IV) return FALSE; desc->gpr.used |= 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->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->gpr.modified |= REGFLAG_R(RDREG); return TRUE; case 0x20: /* ADD */ case 0x22: /* SUB */ case 0x2c: /* DADD */ case 0x2e: /* DSUB */ desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->gpr.modified |= 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->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION; return TRUE; case 0x01: /* MOVF - MIPS IV */ if (mips->flavor < MIPS3_TYPE_MIPS_IV) return FALSE; desc->gpr.used |= REGFLAG_R(RSREG); desc->fpr.used |= REGFLAG_FCC; desc->gpr.modified |= REGFLAG_R(RDREG); return TRUE; case 0x08: /* JR */ desc->gpr.used |= 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->gpr.used |= REGFLAG_R(RSREG); desc->gpr.modified |= 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->gpr.used |= REGFLAG_HI; desc->gpr.modified |= REGFLAG_R(RDREG); return TRUE; case 0x11: /* MTHI */ desc->gpr.used |= REGFLAG_R(RSREG); desc->gpr.modified |= REGFLAG_HI; return TRUE; case 0x12: /* MFLO */ desc->gpr.used |= REGFLAG_LO; desc->gpr.modified |= REGFLAG_R(RDREG); return TRUE; case 0x13: /* MTLO */ desc->gpr.used |= REGFLAG_R(RSREG); desc->gpr.modified |= REGFLAG_LO; return TRUE; case 0x18: /* MULT */ case 0x19: /* MULTU */ desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->gpr.modified |= REGFLAG_LO | REGFLAG_HI; desc->cycles = 3; return TRUE; case 0x1a: /* DIV */ case 0x1b: /* DIVU */ desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->gpr.modified |= REGFLAG_LO | REGFLAG_HI; desc->cycles = 35; return TRUE; case 0x1c: /* DMULT */ case 0x1d: /* DMULTU */ desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->gpr.modified |= REGFLAG_LO | REGFLAG_HI; desc->cycles = 7; return TRUE; case 0x1e: /* DDIV */ case 0x1f: /* DDIVU */ desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->gpr.modified |= 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; } /*------------------------------------------------- describe_instruction_regimm - build a description of a single instruction in the 'regimm' group -------------------------------------------------*/ static int describe_instruction_regimm(mips3_state *mips, 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->gpr.used |= 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->gpr.used |= 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->gpr.used |= REGFLAG_R(RSREG); desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH; } desc->gpr.modified |= REGFLAG_R(31); desc->targetpc = desc->pc + 4 + (SIMMVAL << 2); desc->delayslots = 1; desc->skipslots = (RTREG & 0x02) ? 1 : 0; return TRUE; } return FALSE; } /*------------------------------------------------- describe_instruction_idt - build a description of a single instruction in the IDT-specific group -------------------------------------------------*/ 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; } /*------------------------------------------------- describe_instruction_cop0 - build a description of a single instruction in the COP0 group -------------------------------------------------*/ static int describe_instruction_cop0(mips3_state *mips, 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 */ case 0x02: /* CFCz */ desc->gpr.modified |= REGFLAG_R(RTREG); return TRUE; case 0x04: /* MTCz */ case 0x05: /* DMTCz */ case 0x06: /* CTCz */ desc->gpr.used |= 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_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; return TRUE; } return FALSE; } return FALSE; } /*------------------------------------------------- describe_instruction_cop1 - build a description of a single instruction in the COP1 group -------------------------------------------------*/ static int describe_instruction_cop1(mips3_state *mips, 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->fpr.used |= REGFLAG_CPR1(RDREG); desc->gpr.modified |= REGFLAG_R(RTREG); return TRUE; case 0x02: /* CFCz */ desc->gpr.modified |= REGFLAG_R(RTREG); return TRUE; case 0x04: /* MTCz */ case 0x05: /* DMTCz */ desc->gpr.used |= REGFLAG_R(RTREG); desc->fpr.modified |= REGFLAG_CPR1(RDREG); return TRUE; case 0x06: /* CTCz */ desc->gpr.used |= REGFLAG_R(RTREG); return TRUE; case 0x08: /* BC */ switch (RTREG & 3) { case 0x00: /* BCzF */ case 0x01: /* BCzT */ case 0x02: /* BCzFL */ case 0x03: /* BCzTL */ desc->fpr.used |= 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 (mips->flavor < MIPS3_TYPE_MIPS_IV) return FALSE; case 0x00: /* ADD */ case 0x01: /* SUB */ case 0x02: /* MUL */ case 0x03: /* DIV */ desc->fpr.used |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG); desc->fpr.modified |= REGFLAG_CPR1(FDREG); return TRUE; case 0x15: /* RECIP - MIPS IV */ case 0x16: /* RSQRT - MIPS IV */ if (mips->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->fpr.used |= REGFLAG_CPR1(FSREG); desc->fpr.modified |= REGFLAG_CPR1(FDREG); return TRUE; case 0x11: /* MOVT/F - MIPS IV */ if (mips->flavor < MIPS3_TYPE_MIPS_IV) return FALSE; desc->fpr.used |= REGFLAG_CPR1(FSREG) | REGFLAG_FCC; desc->fpr.modified |= REGFLAG_CPR1(FDREG); return TRUE; case 0x30: case 0x38: /* C.F */ case 0x31: case 0x39: /* C.UN */ desc->fpr.modified |= 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->fpr.used |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG); desc->fpr.modified |= REGFLAG_FCC; return TRUE; } return FALSE; } return FALSE; } /*------------------------------------------------- describe_instruction_cop1x - build a description of a single instruction in the COP1X group -------------------------------------------------*/ static int describe_instruction_cop1x(mips3_state *mips, 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->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->fpr.modified |= REGFLAG_CPR1(FDREG); desc->flags |= OPFLAG_READS_MEMORY; return TRUE; case 0x08: /* SWXC1 */ case 0x09: /* SDXC1 */ desc->gpr.used |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); desc->fpr.used |= 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->fpr.used |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG) | REGFLAG_CPR1(FRREG); desc->fpr.modified |= REGFLAG_CPR1(FDREG); return TRUE; } return FALSE; } /*------------------------------------------------- describe_instruction_cop2 - build a description of a single instruction in the COP2 group -------------------------------------------------*/ static int describe_instruction_cop2(mips3_state *mips, 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->gpr.modified |= REGFLAG_R(RTREG); return TRUE; case 0x04: /* MTCz */ case 0x05: /* DMTCz */ case 0x06: /* CTCz */ desc->gpr.used |= 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; }