static void eps_dd_intersect_list(node * list) { node *l1, *l2; for(l2=list; l2!=NULL; l2=l2->nodelink) { if(is_phi_access(l2)) continue; /* stop second loop after l1 reaches l2 */ for( l1=list; l1 != NULL; l1 = (node *) ( l1==l2 ? NULL : l1->nodelink ) ){ if(is_phi_access(l1)) continue; if ((store_op(l1->nodeop) && store_op(l2->nodeop)) ||(update_op(l1->nodeop) && store_op(l2->nodeop)) ||(store_op(l1->nodeop) && update_op(l2->nodeop))) eps_dd_intersect(l1,l2,ddoutput,ddoutput); if ((store_op(l1->nodeop) && fetch_op(l2->nodeop)) ||(update_op(l1->nodeop) && fetch_op(l2->nodeop)) ||(store_op(l1->nodeop) && update_op(l2->nodeop))) eps_dd_intersect(l1,l2,ddflow,ddanti); if ((fetch_op(l1->nodeop) && store_op(l2->nodeop)) ||(fetch_op(l1->nodeop) && update_op(l2->nodeop)) ||(update_op(l1->nodeop) && store_op(l2->nodeop))) eps_dd_intersect(l1,l2,ddanti,ddflow); if (update_op(l1->nodeop) && update_op(l2->nodeop)) { if (accesses_are_same_update_type(l1,l2)) eps_dd_intersect(l1,l2,ddreduce,ddreduce); else { eps_dd_intersect(l1,l2,ddflow,ddanti); eps_dd_intersect(l1,l2,ddanti,ddflow); eps_dd_intersect(l1,l2,ddoutput,ddoutput); } } } /* for l1 */ } /* for l2 */ }/* eps_dd_intersect_list */
static char *upper_address( UINT32 op, const UINT8 *opram ) { static char s_address[ 20 ]; UINT32 nextop = fetch_op( opram ); if( INS_OP( nextop ) == OP_ORI && INS_RT( op ) == INS_RS( nextop ) ) { sprintf( s_address, "$%04x ; 0x%08x", INS_IMMEDIATE( op ), ( INS_IMMEDIATE( op ) << 16 ) | INS_IMMEDIATE( nextop ) ); } else if( INS_OP( nextop ) == OP_ADDIU && INS_RT( op ) == INS_RS( nextop ) ) { sprintf( s_address, "$%04x ; 0x%08x", INS_IMMEDIATE( op ), ( INS_IMMEDIATE( op ) << 16 ) + (INT16) INS_IMMEDIATE( nextop ) ); } else { sprintf( s_address, "$%04x", INS_IMMEDIATE( op ) ); } return s_address; }
unsigned DasmPSXCPU( psxcpu_state *state, char *buffer, UINT32 pc, const UINT8 *opram ) { UINT32 op; const UINT8 *oldopram; UINT32 flags = 0; oldopram = opram; op = fetch_op( opram ); opram += 4; sprintf( buffer, "dw $%08x", op ); switch( INS_OP( op ) ) { case OP_SPECIAL: switch( INS_FUNCT( op ) ) { case FUNCT_SLL: if( op == 0 ) { /* the standard nop is "sll zero,zero,$0000" */ sprintf( buffer, "nop" ); } else { sprintf( buffer, "sll %s,%s,$%02x", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], INS_SHAMT( op ) ); } break; case FUNCT_SRL: sprintf( buffer, "srl %s,%s,$%02x", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], INS_SHAMT( op ) ); break; case FUNCT_SRA: sprintf( buffer, "sra %s,%s,$%02x", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], INS_SHAMT( op ) ); break; case FUNCT_SLLV: sprintf( buffer, "sllv %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ] ); break; case FUNCT_SRLV: sprintf( buffer, "srlv %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ] ); break; case FUNCT_SRAV: sprintf( buffer, "srav %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ] ); break; case FUNCT_JR: sprintf( buffer, "jr %s", s_cpugenreg[ INS_RS( op ) ] ); if( INS_RS( op ) == 31 ) { flags = DASMFLAG_STEP_OUT; } break; case FUNCT_JALR: sprintf( buffer, "jalr %s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ] ); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA( 1 ); break; case FUNCT_SYSCALL: sprintf( buffer, "syscall $%05x", INS_CODE( op ) ); flags = DASMFLAG_STEP_OVER; break; case FUNCT_BREAK: sprintf( buffer, "break $%05x", INS_CODE( op ) ); flags = DASMFLAG_STEP_OVER; break; case FUNCT_MFHI: sprintf( buffer, "mfhi %s", s_cpugenreg[ INS_RD( op ) ] ); break; case FUNCT_MTHI: sprintf( buffer, "mthi %s", s_cpugenreg[ INS_RS( op ) ] ); break; case FUNCT_MFLO: sprintf( buffer, "mflo %s", s_cpugenreg[ INS_RD( op ) ] ); break; case FUNCT_MTLO: sprintf( buffer, "mtlo %s", s_cpugenreg[ INS_RS( op ) ] ); break; case FUNCT_MULT: sprintf( buffer, "mult %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_MULTU: sprintf( buffer, "multu %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_DIV: sprintf( buffer, "div %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_DIVU: sprintf( buffer, "divu %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_ADD: sprintf( buffer, "add %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_ADDU: sprintf( buffer, "addu %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_SUB: sprintf( buffer, "sub %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_SUBU: sprintf( buffer, "subu %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_AND: sprintf( buffer, "and %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_OR: sprintf( buffer, "or %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_XOR: sprintf( buffer, "xor %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_NOR: sprintf( buffer, "nor %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_SLT: sprintf( buffer, "slt %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; case FUNCT_SLTU: sprintf( buffer, "sltu %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] ); break; } break; case OP_REGIMM: switch( INS_RT_REGIMM( op ) ) { case RT_BLTZ: if( INS_RT( op ) == RT_BLTZAL ) { sprintf( buffer, "bltzal %s,$%08x", s_cpugenreg[ INS_RS( op ) ], relative_address( state, pc, op ) ); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA( 1 ); } else { sprintf( buffer, "bltz %s,$%08x", s_cpugenreg[ INS_RS( op ) ], relative_address( state, pc, op ) ); } break; case RT_BGEZ: if( INS_RT( op ) == RT_BGEZAL ) { sprintf( buffer, "bgezal %s,$%08x", s_cpugenreg[ INS_RS( op ) ], relative_address( state, pc, op ) ); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA( 1 ); } else { sprintf( buffer, "bgez %s,$%08x", s_cpugenreg[ INS_RS( op ) ], relative_address( state, pc, op ) ); } break; } break; case OP_J: sprintf( buffer, "j $%08x", jump_address( state, pc, op ) ); break; case OP_JAL: sprintf( buffer, "jal $%08x", jump_address( state, pc, op ) ); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA( 1 ); break; case OP_BEQ: sprintf( buffer, "beq %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], relative_address( state, pc, op ) ); break; case OP_BNE: sprintf( buffer, "bne %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], relative_address( state, pc, op ) ); break; case OP_BLEZ: sprintf( buffer, "blez %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], relative_address( state, pc, op ) ); break; case OP_BGTZ: sprintf( buffer, "bgtz %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], relative_address( state, pc, op ) ); break; case OP_ADDI: sprintf( buffer, "addi %s,%s,%s", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], make_signed_hex_str_16( INS_IMMEDIATE( op ) ) ); break; case OP_ADDIU: sprintf( buffer, "addiu %s,%s,%s", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], make_signed_hex_str_16( INS_IMMEDIATE( op ) ) ); break; case OP_SLTI: sprintf( buffer, "slti %s,%s,%s", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], make_signed_hex_str_16( INS_IMMEDIATE( op ) ) ); break; case OP_SLTIU: sprintf( buffer, "sltiu %s,%s,%s", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], make_signed_hex_str_16( INS_IMMEDIATE( op ) ) ); break; case OP_ANDI: sprintf( buffer, "andi %s,%s,$%04x", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], INS_IMMEDIATE( op ) ); break; case OP_ORI: sprintf( buffer, "ori %s,%s,$%04x", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], INS_IMMEDIATE( op ) ); break; case OP_XORI: sprintf( buffer, "xori %s,%s,$%04x", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], INS_IMMEDIATE( op ) ); break; case OP_LUI: sprintf( buffer, "lui %s,%s", s_cpugenreg[ INS_RT( op ) ], upper_address( op, opram ) ); break; case OP_COP0: switch( INS_RS( op ) ) { case RS_MFC: sprintf( buffer, "mfc0 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp0genreg[ INS_RD( op ) ] ); break; case RS_CFC: sprintf( buffer, "!cfc0 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp0ctlreg[ INS_RD( op ) ] ); break; case RS_MTC: sprintf( buffer, "mtc0 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp0genreg[ INS_RD( op ) ] ); break; case RS_CTC: sprintf( buffer, "!ctc0 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp0ctlreg[ INS_RD( op ) ] ); break; case RS_BC: case RS_BC_ALT: switch( INS_BC( op ) ) { case BC_BCF: sprintf( buffer, "bc0f $%08x", relative_address( state, pc, op ) ); break; case BC_BCT: sprintf( buffer, "bc0t $%08x", relative_address( state, pc, op ) ); break; } break; default: switch( INS_CO( op ) ) { case 1: sprintf( buffer, "cop0 $%07x", INS_COFUN( op ) ); switch( INS_CF( op ) ) { case CF_TLBR: sprintf( buffer, "!tlbr" ); break; case CF_TLBWI: sprintf( buffer, "!tlbwi" ); break; case CF_TLBWR: sprintf( buffer, "!tlbwr" ); break; case CF_TLBP: sprintf( buffer, "!tlbp" ); break; case CF_RFE: sprintf( buffer, "rfe" ); break; } break; } break; } break; case OP_COP1: switch( INS_RS( op ) ) { case RS_MFC: sprintf( buffer, "mfc1 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp1genreg[ INS_RD( op ) ] ); break; case RS_CFC: sprintf( buffer, "cfc1 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp1ctlreg[ INS_RD( op ) ] ); break; case RS_MTC: sprintf( buffer, "mtc1 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp1genreg[ INS_RD( op ) ] ); break; case RS_CTC: sprintf( buffer, "ctc1 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp1ctlreg[ INS_RD( op ) ] ); break; case RS_BC: case RS_BC_ALT: switch( INS_BC( op ) ) { case BC_BCF: sprintf( buffer, "bc1f $%08x", relative_address( state, pc, op ) ); break; case BC_BCT: sprintf( buffer, "bc1t $%08x", relative_address( state, pc, op ) ); break; } break; default: switch( INS_CO( op ) ) { case 1: sprintf( buffer, "cop1 $%07x", INS_COFUN( op ) ); break; } break; } break; case OP_COP2: switch( INS_RS( op ) ) { case RS_MFC: sprintf( buffer, "mfc2 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp2genreg[ INS_RD( op ) ] ); break; case RS_CFC: sprintf( buffer, "cfc2 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp2ctlreg[ INS_RD( op ) ] ); break; case RS_MTC: sprintf( buffer, "mtc2 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp2genreg[ INS_RD( op ) ] ); break; case RS_CTC: sprintf( buffer, "ctc2 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp2ctlreg[ INS_RD( op ) ] ); break; case RS_BC: case RS_BC_ALT: switch( INS_BC( op ) ) { case BC_BCF: sprintf( buffer, "bc2f $%08x", relative_address( state, pc, op ) ); break; case BC_BCT: sprintf( buffer, "bc2t $%08x", relative_address( state, pc, op ) ); break; } break; default: switch( INS_CO( op ) ) { case 1: sprintf( buffer, "cop2 $%07x", INS_COFUN( op ) ); switch( GTE_FUNCT( op ) ) { case 0x00: // drop through to RTPS case 0x01: sprintf( buffer, "rtps%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x06: sprintf( buffer, "nclip" ); break; case 0x0c: sprintf( buffer, "op%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x10: sprintf( buffer, "dpcs%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x11: sprintf( buffer, "intpl%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x12: sprintf( buffer, "mvmva%s%s %s + %s * %s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ], s_gtecv[ GTE_CV( op ) ], s_gtemx[ GTE_MX( op ) ], s_gtev[ GTE_V( op ) ] ); break; case 0x13: sprintf( buffer, "ncds%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x14: sprintf( buffer, "cdp%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x16: sprintf( buffer, "ncdt%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x1b: sprintf( buffer, "nccs%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x1c: sprintf( buffer, "cc%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x1e: sprintf( buffer, "ncs%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x20: sprintf( buffer, "nct%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x28: sprintf( buffer, "sqr%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x1a: // end of NCDT case 0x29: sprintf( buffer, "dpcl%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x2a: sprintf( buffer, "dpct%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x2d: sprintf( buffer, "avsz3" ); break; case 0x2e: sprintf( buffer, "avsz4" ); break; case 0x30: sprintf( buffer, "rtpt%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x3d: sprintf( buffer, "gpf%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x3e: sprintf( buffer, "gpl%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; case 0x3f: sprintf( buffer, "ncct%s%s", s_gtesf[ GTE_SF( op ) ], s_gtelm[ GTE_LM( op ) ] ); break; } } break; } break; case OP_COP3: switch( INS_RS( op ) ) { case RS_MFC: sprintf( buffer, "mfc3 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp3genreg[ INS_RD( op ) ] ); break; case RS_CFC: sprintf( buffer, "cfc3 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp3ctlreg[ INS_RD( op ) ] ); break; case RS_MTC: sprintf( buffer, "mtc3 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp3genreg[ INS_RD( op ) ] ); break; case RS_CTC: sprintf( buffer, "ctc3 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp3ctlreg[ INS_RD( op ) ] ); break; case RS_BC: case RS_BC_ALT: switch( INS_BC( op ) ) { case BC_BCF: sprintf( buffer, "bc3f $%08x", relative_address( state, pc, op ) ); break; case BC_BCT: sprintf( buffer, "bc3t $%08x", relative_address( state, pc, op ) ); break; } break; default: switch( INS_CO( op ) ) { case 1: sprintf( buffer, "cop3 $%07x", INS_COFUN( op ) ); break; } break; } break; case OP_LB: sprintf( buffer, "lb %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LH: sprintf( buffer, "lh %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LWL: sprintf( buffer, "lwl %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LW: sprintf( buffer, "lw %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LBU: sprintf( buffer, "lbu %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LHU: sprintf( buffer, "lhu %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LWR: sprintf( buffer, "lwr %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SB: sprintf( buffer, "sb %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SH: sprintf( buffer, "sh %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SWL: sprintf( buffer, "swl %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SW: sprintf( buffer, "sw %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SWR: sprintf( buffer, "swr %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LWC0: sprintf( buffer, "lwc0 %s,%s", s_cp0genreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LWC1: sprintf( buffer, "lwc1 %s,%s", s_cp1genreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LWC2: sprintf( buffer, "lwc2 %s,%s", s_cp2genreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_LWC3: sprintf( buffer, "lwc3 %s,%s", s_cp2genreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SWC0: sprintf( buffer, "swc0 %s,%s", s_cp0genreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SWC1: sprintf( buffer, "swc1 %s,%s", s_cp1genreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SWC2: sprintf( buffer, "swc2 %s,%s", s_cp2genreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; case OP_SWC3: sprintf( buffer, "swc3 %s,%s", s_cp2genreg[ INS_RT( op ) ], effective_address( state, pc, op ) ); break; } return ( opram - oldopram ) | flags | DASMFLAG_SUPPORTED; }
/** * @brief emulate instruction * @return returns false if something goes wrong (e.g. illegal instruction) * * Current limitations: * * - Illegal instructions are not implemented * - Excess cycles due to page boundary crossing are not calculated * - Some known architectural bugs are not emulated */ bool Cpu::emulate() { /* fetch instruction */ uint8_t insn = fetch_op(); bool retval = true; /* emulate instruction */ switch(insn) { /* BRK */ case 0x0: brk(); break; /* ORA (nn,X) */ case 0x1: ora(load_byte(addr_indx()),6); break; /* ORA nn */ case 0x5: ora(load_byte(addr_zero()),3); break; /* ASL nn */ case 0x6: asl_mem(addr_zero(),5); break; /* PHP */ case 0x8: php(); break; /* ORA #nn */ case 0x9: ora(fetch_op(),2); break; /* ASL A */ case 0xA: asl_a(); break; /* ORA nnnn */ case 0xD: ora(load_byte(addr_abs()),4); break; /* ASL nnnn */ case 0xE: asl_mem(addr_abs(),6); break; /* BPL nn */ case 0x10: bpl(); break; /* ORA (nn,Y) */ case 0x11: ora(load_byte(addr_indy()),5); break; /* ORA nn,X */ case 0x15: ora(load_byte(addr_zerox()),4); break; /* ASL nn,X */ case 0x16: asl_mem(addr_zerox(),6); break; /* CLC */ case 0x18: clc(); break; /* ORA nnnn,Y */ case 0x19: ora(load_byte(addr_absy()),4); break; /* ORA nnnn,X */ case 0x1D: ora(load_byte(addr_absx()),4); break; /* ASL nnnn,X */ case 0x1E: asl_mem(addr_absx(),7); break; /* JSR */ case 0x20: jsr(); break; /* AND (nn,X) */ case 0x21: _and(load_byte(addr_indx()),6); break; /* BIT nn */ case 0x24: bit(addr_zero(),3); break; /* AND nn */ case 0x25: _and(load_byte(addr_zero()),3); break; /* ROL nn */ case 0x26: rol_mem(addr_zero(),5); break; /* PLP */ case 0x28: plp(); break; /* AND #nn */ case 0x29: _and(fetch_op(),2); break; /* ROL A */ case 0x2A: rol_a(); break; /* BIT nnnn */ case 0x2C: bit(addr_abs(),4); break; /* AND nnnn */ case 0x2D: _and(load_byte(addr_abs()),4); break; /* ROL nnnn */ case 0x2E: rol_mem(addr_abs(),6); break; /* BMI nn */ case 0x30: bmi(); break; /* AND (nn,Y) */ case 0x31: _and(load_byte(addr_indy()),5); break; /* AND nn,X */ case 0x35: _and(load_byte(addr_zerox()),4); break; /* ROL nn,X */ case 0x36: rol_mem(addr_zerox(),6); break; /* SEC */ case 0x38: sec(); break; /* AND nnnn,Y */ case 0x39: _and(load_byte(addr_absy()),4); break; /* AND nnnn,X */ case 0x3D: _and(load_byte(addr_absx()),4); break; /* ROL nnnn,X */ case 0x3E: rol_mem(addr_absx(),7); break; /* RTI */ case 0x40: rti(); break; /* EOR (nn,X) */ case 0x41: eor(load_byte(addr_indx()),6); break; /* EOR nn */ case 0x45: eor(load_byte(addr_zero()),3); break; /* LSR nn */ case 0x46: lsr_mem(addr_zero(),5); break; /* PHA */ case 0x48: pha(); break; /* EOR #nn */ case 0x49: eor(fetch_op(),2); break; /* BVC */ case 0x50: bvc(); break; /* JMP nnnn */ case 0x4C: jmp(); break; /* EOR nnnn */ case 0x4D: eor(load_byte(addr_abs()),4); break; /* LSR A */ case 0x4A: lsr_a(); break; /* LSR nnnn */ case 0x4E: lsr_mem(addr_abs(),6); break; /* EOR (nn,Y) */ case 0x51: eor(load_byte(addr_indy()),5); break; /* EOR nn,X */ case 0x55: eor(load_byte(addr_zerox()),4); break; /* LSR nn,X */ case 0x56: lsr_mem(addr_zerox(),6); break; /* CLI */ case 0x58: cli(); break; /* EOR nnnn,Y */ case 0x59: eor(load_byte(addr_absy()),4); break; /* EOR nnnn,X */ case 0x5D: eor(load_byte(addr_absx()),4); break; /* LSR nnnn,X */ case 0x5E: lsr_mem(addr_absx(),7); break; /* RTS */ case 0x60: rts(); break; /* ADC (nn,X) */ case 0x61: adc(load_byte(addr_indx()),6); break; /* ADC nn */ case 0x65: adc(load_byte(addr_zero()),3); break; /* ROR nn */ case 0x66: ror_mem(addr_zero(),5); break; /* PLA */ case 0x68: pla(); break; /* ADC #nn */ case 0x69: adc(fetch_op(),2); break; /* ROR A */ case 0x6A: ror_a(); break; /* JMP (nnnn) */ case 0x6C: jmp_ind(); break; /* ADC nnnn */ case 0x6D: adc(load_byte(addr_abs()),4); break; /* ROR nnnn */ case 0x6E: ror_mem(addr_abs(),6); break; /* BVS */ case 0x70: bvs(); break; /* ADC (nn,Y) */ case 0x71: adc(load_byte(addr_indy()),5); break; /* ADC nn,X */ case 0x75: adc(load_byte(addr_zerox()),4); break; /* ROR nn,X */ case 0x76: ror_mem(addr_zerox(),6); break; /* SEI */ case 0x78: sei(); break; /* ADC nnnn,Y */ case 0x79: adc(load_byte(addr_absy()),4); break; /* ADC nnnn,X */ case 0x7D: adc(load_byte(addr_absx()),4); break; /* ROR nnnn,X */ case 0x7E: ror_mem(addr_absx(),7); break; /* STA (nn,X) */ case 0x81: sta(addr_indx(),6); break; /* STY nn */ case 0x84: sty(addr_zero(),3); break; /* STA nn */ case 0x85: sta(addr_zero(),3); break; /* STX nn */ case 0x86: stx(addr_zero(),3); break; /* DEY */ case 0x88: dey(); break; /* TXA */ case 0x8A: txa(); break; /* STY nnnn */ case 0x8C: sty(addr_abs(),4); break; /* STA nnnn */ case 0x8D: sta(addr_abs(),4); break; /* STX nnnn */ case 0x8E: stx(addr_abs(),4); break; /* BCC nn */ case 0x90: bcc(); break; /* STA (nn,Y) */ case 0x91: sta(addr_indy(),6); break; /* STY nn,X */ case 0x94: sty(addr_zerox(),4); break; /* STA nn,X */ case 0x95: sta(addr_zerox(),4); break; /* STX nn,Y */ case 0x96: stx(addr_zeroy(),4); break; /* TYA */ case 0x98: tya(); break; /* STA nnnn,Y */ case 0x99: sta(addr_absy(),5); break; /* TXS */ case 0x9A: txs(); break; /* STA nnnn,X */ case 0x9D: sta(addr_absx(),5); break; /* LDY #nn */ case 0xA0: ldy(fetch_op(),2); break; /* LDA (nn,X) */ case 0xA1: lda(load_byte(addr_indx()),6); break; /* LDX #nn */ case 0xA2: ldx(fetch_op(),2); break; /* LDY nn */ case 0xA4: ldy(load_byte(addr_zero()),3); break; /* LDA nn */ case 0xA5: lda(load_byte(addr_zero()),3); break; /* LDX nn */ case 0xA6: ldx(load_byte(addr_zero()),3); break; /* TAY */ case 0xA8: tay(); break; /* LDA #nn */ case 0xA9: lda(fetch_op(),2); break; /* TAX */ case 0xAA: tax(); break; /* LDY nnnn */ case 0xAC: ldy(load_byte(addr_abs()),4); break; /* LDA nnnn */ case 0xAD: lda(load_byte(addr_abs()),4); break; /* LDX nnnn */ case 0xAE: ldx(load_byte(addr_abs()),4); break; /* BCS nn */ case 0xB0: bcs(); break; /* LDA (nn,Y) */ case 0xB1: lda(load_byte(addr_indy()),5); break; /* LDY nn,X */ case 0xB4: ldy(load_byte(addr_zerox()),3); break; /* LDA nn,X */ case 0xB5: lda(load_byte(addr_zerox()),3); break; /* LDX nn,Y */ case 0xB6: ldx(load_byte(addr_zeroy()),3); break; /* CLV */ case 0xB8: clv(); break; /* LDA nnnn,Y */ case 0xB9: lda(load_byte(addr_absy()),4); break; /* TSX */ case 0xBA: tsx(); break; /* LDY nnnn,X */ case 0xBC: ldy(load_byte(addr_absx()),4); break; /* LDA nnnn,X */ case 0xBD: lda(load_byte(addr_absx()),4); break; /* LDX nnnn,Y */ case 0xBE: ldx(load_byte(addr_absy()),4); break; /* CPY #nn */ case 0xC0: cpy(fetch_op(),2); break; /* CMP (nn,X) */ case 0xC1: cmp(load_byte(addr_indx()),6); break; /* CPY nn */ case 0xC4: cpy(load_byte(addr_zero()),3); break; /* CMP nn */ case 0xC5: cmp(load_byte(addr_zero()),3); break; /* DEC nn */ case 0xC6: dec(addr_zero(),5); break; /* INY */ case 0xC8: iny(); break; /* CMP #nn */ case 0xC9: cmp(fetch_op(),2); break; /* DEX */ case 0xCA: dex(); break; /* CPY nnnn */ case 0xCC: cpy(load_byte(addr_abs()),4); break; /* CMP nnnn */ case 0xCD: cmp(load_byte(addr_abs()),4); break; /* DEC nnnn */ case 0xCE: dec(addr_abs(),6); break; /* BNE nn */ case 0xD0: bne(); break; /* CMP (nn,Y) */ case 0xD1: cmp(load_byte(addr_indy()),5); break; /* CMP nn,X */ case 0xD5: cmp(load_byte(addr_zerox()),4); break; /* DEC nn,X */ case 0xD6: dec(addr_zerox(),6); break; /* CLD */ case 0xD8: cld(); break; /* CMP nnnn,Y */ case 0xD9: cmp(load_byte(addr_absy()),4); break; /* CMP nnnn,X */ case 0xDD: cmp(load_byte(addr_absx()),4); break; /* DEC nnnn,X */ case 0xDE: dec(addr_absx(),7); break; /* CPX #nn */ case 0xE0: cpx(fetch_op(),2); break; /* SBC (nn,X) */ case 0xE1: sbc(load_byte(addr_indx()),6); break; /* CPX nn */ case 0xE4: cpx(load_byte(addr_zero()),3); break; /* SBC nn */ case 0xE5: sbc(load_byte(addr_zero()),3); break; /* INC nn */ case 0xE6: inc(addr_zero(),5); break; /* INX */ case 0xE8: inx(); break; /* SBC #nn */ case 0xE9: sbc(fetch_op(),2); break; /* NOP */ case 0xEA: nop(); break; /* CPX nnnn */ case 0xEC: cpx(load_byte(addr_abs()),4); break; /* SBC nnnn */ case 0xED: sbc(load_byte(addr_abs()),4); break; /* INC nnnn */ case 0xEE: inc(addr_abs(),6); break; /* BEQ nn */ case 0xF0: beq(); break; /* SBC (nn,Y) */ case 0xF1: sbc(load_byte(addr_indy()),5); break; /* SBC nn,X */ case 0xF5: sbc(load_byte(addr_zerox()),4); break; /* INC nn,X */ case 0xF6: inc(addr_zerox(),6); break; /* SED */ case 0xF8: sed(); break; /* SBC nnnn,Y */ case 0xF9: sbc(load_byte(addr_absy()),4); break; /* SBC nnnn,X */ case 0xFD: sbc(load_byte(addr_absx()),4); break; /* INC nnnn,X */ case 0xFE: inc(addr_absx(),7); break; /* Unknown or illegal instruction */ default: D("Unknown instruction: %X at %04x\n", insn,pc()); retval = false; } return retval; }
uint16_t Cpu::addr_zeroy() { /* wraps around the zeropage */ uint16_t addr = (fetch_op() + y()) & 0xff; return addr; }
uint16_t Cpu::addr_zero() { uint16_t addr = fetch_op(); return addr; }