disasmif.c 2.58 KB
#include <string.h>
#include "opcode.h"

extern int regsUsed;

void rspDis_init( char *addr_format, char *value_format, char *reg_names[],
	int print_jal_targets )
{
	/* well, just don't do anything */
}

void rspDis_regs( char *buffer, unsigned regmask, unsigned reg_values[] )
{
	register int i, displayed = 0;
	unsigned int whichReg = 2;	/* start at reg 1 */

	for ( i = 1; i < 32; ++i, whichReg <<= 1 )
	{
		if ( regmask & whichReg )
		{
			if ( displayed )
				strcat( buffer, "," );
			else
				strcat( buffer, "\t<" );
			sprintf( buffer + strlen( buffer ), "$%d=0x%d",
				i, reg_values[i] );
			++displayed;
		}

	}
	if ( displayed )
		strcat( buffer, ">" );
}

extern void rsp_DisasmInst( unsigned int, char *, int );

int rspDisasmReturnType( unsigned int inst )
{
	switch ( ExtractOpcode( inst ) )
	{
	case rsp_SPECIAL:
		switch ( ExtractBits( inst, 5, 0 ) )
		{
		case rsp_JR:
		case rsp_JALR:
			return 2;

		default:
			return 0;
		}

	case rsp_REGIMM:
		switch ( ExtractBits(inst, 20, 16) )
		{
		case rsp_BLTZ:
		case rsp_BGEZ:
		case rsp_BLTZAL:
		case rsp_BGEZAL:
			return 2;
		
		default:
			return 0;
		}

	case rsp_COP0:
		switch( ExtractBits(inst, 25, 21) )
		{
		case rsp_BC0:
			return 2;

		case rsp_MFC0:
		case rsp_MTC0:
			regsUsed = 1 << ExtractBits( inst, 20, 16 );
		default:
			return 0;
		}

	case rsp_COP2:
		regsUsed = 0;
		switch( ExtractBits(inst, 25, 21) )
		{
		case rsp_BC:
			return 2;

		case rsp_MFC2:
		case rsp_CFC2:
		case rsp_MTC2:
		case rsp_CTC2:
			regsUsed = 1 << ExtractBits( inst, 20, 16 );
		default:
			return 0;
		}

	case rsp_J: 
	case rsp_BEQ: 
	case rsp_BNE: 
	case rsp_BLEZ: 
	case rsp_BGTZ:
		return 2;

	case rsp_JAL:
		return 1;

	case rsp_LWC2:
	case rsp_SWC2:
		regsUsed = 1 << ExtractBits( inst, 25, 21 );
	/* and fall through to */
	case rsp_LB: 
	case rsp_LBU:
	case rsp_LH: 
	case rsp_LHU:
	case rsp_LW:
	case rsp_SB: 
	case rsp_SH: 
	case rsp_SW:
	case rsp_LUI:
		return -1;

	default:
		break;
	}
	return 0;
}

int rspDisasm( char *buffer, unsigned address, unsigned iword, unsigned *regmask,
	unsigned *symbol_value, unsigned *ls_register )
{
	int retval;
	short immed;

	rsp_DisasmInst( iword, buffer, address );
	*symbol_value = 0;	/* target or load address */
	retval = rspDisasmReturnType( iword );
	if ( retval == -1 )	/* load or store */
	{
		*ls_register = ExtractBits( iword, 25, 21 );
		immed = iword & 0xffff;
		*symbol_value = (int) immed;
	}
	else  if ( retval == 1 )
	{
		*symbol_value = ((iword << 2) & 0xfff) + 0x4001000;	/* 12 bit addr! */
		strcpy( buffer, "jal\t" );
	}
	*regmask = regsUsed;		/* should be the regs used by the inst */
	return retval;
}