Example #1
0
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;
}
Example #2
0
unsigned DasmMIPS( char *buffer, UINT32 pc, const UINT8 *opram )
{
	UINT32 op;
	const UINT8 *oldopram;

	oldopram = opram;
	op = ( opram[ 3 ] << 24 ) | ( opram[ 2 ] << 16 ) | ( opram[ 1 ] << 8 ) | ( opram[ 0 ] << 0 );
	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:
			if( INS_RD( op ) == 0 )
			{
				sprintf( buffer, "jr      %s", s_cpugenreg[ INS_RS( op ) ] );
			}
			break;
		case FUNCT_JALR:
			sprintf( buffer, "jalr    %s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ] );
			break;
		case FUNCT_SYSCALL:
			sprintf( buffer, "syscall $%05x", INS_CODE( op ) );
			break;
		case FUNCT_BREAK:
			sprintf( buffer, "break   $%05x", INS_CODE( op ) );
			break;
		case FUNCT_MFHI:
			sprintf( buffer, "mfhi    %s", s_cpugenreg[ INS_RD( op ) ] );
			break;
		case FUNCT_MTHI:
			if( INS_RD( op ) == 0 )
			{
				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:
			if( INS_RD( op ) == 0 )
			{
				sprintf( buffer, "mtlo    %s", s_cpugenreg[ INS_RS( op ) ] );
			}
			break;
		case FUNCT_MULT:
			if( INS_RD( op ) == 0 )
			{
				sprintf( buffer, "mult    %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
			}
			break;
		case FUNCT_MULTU:
			if( INS_RD( op ) == 0 )
			{
				sprintf( buffer, "multu   %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
			}
			break;
		case FUNCT_DIV:
			if( INS_RD( op ) == 0 )
			{
				sprintf( buffer, "div     %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
			}
			break;
		case FUNCT_DIVU:
			if( INS_RD( op ) == 0 )
			{
				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( op ) )
		{
		case RT_BLTZ:
			sprintf( buffer, "bltz    %s,$%08x", s_cpugenreg[ INS_RS( op ) ], pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
			break;
		case RT_BGEZ:
			sprintf( buffer, "bgez    %s,$%08x", s_cpugenreg[ INS_RS( op ) ], pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
			break;
		case RT_BLTZAL:
			sprintf( buffer, "bltzal  %s,$%08x", s_cpugenreg[ INS_RS( op ) ], pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
			break;
		case RT_BGEZAL:
			sprintf( buffer, "bgezal  %s,$%08x", s_cpugenreg[ INS_RS( op ) ], pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
			break;
		}
		break;
	case OP_J:
		sprintf( buffer, "j       $%08x", ( ( pc + 4 ) & 0xF0000000 ) + ( INS_TARGET( op ) << 2 ) );
		break;
	case OP_JAL:
		sprintf( buffer, "jal     $%08x", ( ( pc + 4 ) & 0xF0000000 ) + ( INS_TARGET( op ) << 2 ) );
		break;
	case OP_BEQ:
		sprintf( buffer, "beq     %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
		break;
	case OP_BNE:
		sprintf( buffer, "bne     %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
		break;
	case OP_BLEZ:
		if( INS_RT( op ) == 0 )
		{
			sprintf( buffer, "blez    %s,$%08x", s_cpugenreg[ INS_RS( op ) ], pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
		}
		break;
	case OP_BGTZ:
		if( INS_RT( op ) == 0 )
		{
			sprintf( buffer, "bgtz    %s,$%08x", s_cpugenreg[ INS_RS( op ) ], pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
		}
		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,$%04x", s_cpugenreg[ INS_RT( op ) ], INS_IMMEDIATE( op ) );
		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_MTC:
			sprintf( buffer, "mtc0    %s,%s",  s_cpugenreg[ INS_RT( op ) ], s_cp0genreg[ INS_RD( op ) ] );
			break;
		case RS_BC:
			switch( INS_RT( op ) )
			{
			case RT_BCF:
				sprintf( buffer, "bc0f    $%08x", pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
				break;
			case RT_BCT:
				sprintf( buffer, "bc0t    $%08x", pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
				break;
			}
			break;
		default:
			switch( INS_CO( op ) )
			{
			case 1:
				sprintf( buffer, "cop0    $%07x", INS_COFUN( op ) );

				switch( INS_CF( op ) )
				{
				case 1:
					sprintf( buffer, "tlbr" );
					break;
				case 4:
					sprintf( buffer, "tlbwi" );
					break;
				case 6:
					sprintf( buffer, "tlbwr" );
					break;
				case 8:
					sprintf( buffer, "tlbp" );
					break;
				case 16:
					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:
			switch( INS_RT( op ) )
			{
			case RT_BCF:
				sprintf( buffer, "bc1f    $%08x", pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
				break;
			case RT_BCT:
				sprintf( buffer, "bc1t    $%08x", pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
				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:
			switch( INS_RT( op ) )
			{
			case RT_BCF:
				sprintf( buffer, "bc2f    $%08x", pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
				break;
			case RT_BCT:
				sprintf( buffer, "bc2t    $%08x", pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 ) );
				break;
			}
			break;
		default:
			switch( INS_CO( op ) )
			{
			case 1:
				sprintf( buffer, "cop2    $%07x", INS_COFUN( op ) );

				switch( GTE_FUNCT( op ) )
				{
				case 0x01:
					if( INS_COFUN( op ) == 0x0180001 )
					{
						sprintf( buffer, "rtps" );
					}
					break;
				case 0x06:
					if( INS_COFUN( op ) == 0x0400006 ||
						INS_COFUN( op ) == 0x1400006 ||
						INS_COFUN( op ) == 0x0155cc6 )
					{
						sprintf( buffer, "nclip" );
					}
					break;
				case 0x0c:
					if( GTE_OP( op ) == 0x17 )
					{
						sprintf( buffer, "op%s", s_gtesf[ GTE_SF( op ) ] );
					}
					break;
				case 0x10:
					if( INS_COFUN( op ) == 0x0780010 )
					{
						sprintf( buffer, "dpcs" );
					}
					break;
				case 0x11:
					if( INS_COFUN( op ) == 0x0980011 )
					{
						sprintf( buffer, "intpl" );
					}
					break;
				case 0x12:
					if( GTE_OP( op ) == 0x04 )
					{
						sprintf( buffer, "mvmva%s %s + %s * %s (lm=%s)",
							s_gtesf[ GTE_SF( op ) ], s_gtecv[ GTE_CV( op ) ], s_gtemx[ GTE_MX( op ) ],
							s_gtev[ GTE_V( op ) ],  s_gtelm[ GTE_LM( op ) ] );
					}
					break;
				case 0x13:
					if( INS_COFUN( op ) == 0x0e80413 )
					{
						sprintf( buffer, "ncds" );
					}
					break;
				case 0x14:
					if( INS_COFUN( op ) == 0x1280414 )
					{
						sprintf( buffer, "cdp" );
					}
					break;
				case 0x16:
					if( INS_COFUN( op ) == 0x0f80416 )
					{
						sprintf( buffer, "ncdt" );
					}
					break;
				case 0x1b:
					if( INS_COFUN( op ) == 0x108041b )
					{
						sprintf( buffer, "nccs" );
					}
					break;
				case 0x1c:
					if( INS_COFUN( op ) == 0x138041c )
					{
						sprintf( buffer, "cc" );
					}
					break;
				case 0x1e:
					if( INS_COFUN( op ) == 0x0c8041e )
					{
						sprintf( buffer, "ncs" );
					}
					break;
				case 0x20:
					if( INS_COFUN( op ) == 0x0d80420 )
					{
						sprintf( buffer, "nct" );
					}
					break;
				case 0x28:
					if( GTE_OP( op ) == 0x0a && GTE_LM( op ) == 1 )
					{
						sprintf( buffer, "sqr%s", s_gtesf[ GTE_SF( op ) ] );
					}
					break;
				case 0x29:
					if( INS_COFUN( op ) == 0x0680029 )
					{
						sprintf( buffer, "dcpl" );
					}
					break;
				case 0x2a:
					if( INS_COFUN( op ) == 0x0f8002a )
					{
						sprintf( buffer, "dpct" );
					}
					break;
				case 0x2d:
					if( INS_COFUN( op ) == 0x158002d )
					{
						sprintf( buffer, "avsz3" );
					}
					break;
				case 0x2e:
					if( INS_COFUN( op ) == 0x168002e )
					{
						sprintf( buffer, "avsz4" );
					}
					break;
				case 0x30:
					if( INS_COFUN( op ) == 0x0280030 )
					{
						sprintf( buffer, "rtpt" );
					}
					break;
				case 0x3d:
					if( GTE_OP( op ) == 0x09 ||
						GTE_OP( op ) == 0x19 )
					{
						sprintf( buffer, "gpf%s", s_gtesf[ GTE_SF( op ) ] );
					}
					break;
				case 0x3e:
					if( GTE_OP( op ) == 0x1a )
					{
						sprintf( buffer, "gpl%s", s_gtesf[ GTE_SF( op ) ] );
					}
					break;
				case 0x3f:
					if( INS_COFUN( op ) == 0x108043f ||
						INS_COFUN( op ) == 0x118043f )
					{
						sprintf( buffer, "ncct" );
					}
					break;
				}
			}
			break;
		}
		break;
	case OP_LB:
		sprintf( buffer, "lb      %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_LH:
		sprintf( buffer, "lh      %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_LWL:
		sprintf( buffer, "lwl     %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_LW:
		sprintf( buffer, "lw      %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_LBU:
		sprintf( buffer, "lbu     %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_LHU:
		sprintf( buffer, "lhu     %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_LWR:
		sprintf( buffer, "lwr     %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_SB:
		sprintf( buffer, "sb      %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_SH:
		sprintf( buffer, "sh      %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_SWL:
		sprintf( buffer, "swl     %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_SW:
		sprintf( buffer, "sw      %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_SWR:
		sprintf( buffer, "swr     %s,%s", s_cpugenreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_LWC1:
		sprintf( buffer, "lwc1    %s,%s", s_cp1genreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_LWC2:
		sprintf( buffer, "lwc2    %s,%s", s_cp2genreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_SWC1:
		sprintf( buffer, "swc1    %s,%s", s_cp1genreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	case OP_SWC2:
		sprintf( buffer, "swc2    %s,%s", s_cp2genreg[ INS_RT( op ) ], make_address( pc, op ) );
		break;
	}
	return ( opram - oldopram ) | DASMFLAG_SUPPORTED;
}