<commit_before>#include "stdafx.h"
#include "CMipsInstruction.h"
#include "Core/Common.h"
#include "Mips.h"
#include "MipsOpcodes.h"
#include "Core/FileManager.h"
#include "MipsParser.h"

CMipsInstruction::CMipsInstruction(MipsOpcodeData& opcode, MipsImmediateData& immediate, MipsRegisterData& registers)
{
	this->opcodeData = opcode;
	this->immediateData = immediate;
	this->registerData = registers;

	addNop = false;
	IgnoreLoadDelay = Mips.GetIgnoreDelay();
}

CMipsInstruction::~CMipsInstruction()
{

}

int getImmediateBits(MipsImmediateType type)
{
	switch (type)
	{
	case MipsImmediateType::Immediate5:
		return 5;
	case MipsImmediateType::Immediate7:
		return 7;
	case MipsImmediateType::Immediate8:
		return 8;
	case MipsImmediateType::Immediate16:
	case MipsImmediateType::ImmediateHalfFloat:
		return 16;
	case MipsImmediateType::Immediate20:
	case MipsImmediateType::Immediate20_0:
		return 20;
	case MipsImmediateType::Immediate26:
		return 26;
	default:
		return 0;
	}
}

// http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/Allegrex/VfpuState.java?spec=svn3676&r=3383#1196
int CMipsInstruction::floatToHalfFloat(int i)
{
	int s = ((i >> 16) & 0x00008000); // sign
	int e = ((i >> 23) & 0x000000ff) - (127 - 15); // exponent
	int f = ((i >> 0) & 0x007fffff); // fraction

	// need to handle NaNs and Inf?
	if (e <= 0) {
		if (e < -10) {
			if (s != 0) {
				// handle -0.0
				return 0x8000;
			}
			return 0;
		}
		f = (f | 0x00800000) >> (1 - e);
		return s | (f >> 13);
	} else if (e == 0xff - (127 - 15)) {
		if (f == 0) {
			// Inf
			return s | 0x7c00;
		}
		// NAN
		return s | 0x7fff;
	}

	if (e > 30) {
		// Overflow
		return s | 0x7c00;
	}

	return s | (e << 10) | (f >> 13);
}

bool CMipsInstruction::Validate()
{
	bool Result = false;

	bool previousNop = addNop;
	addNop = false;

	RamPos = g_fileManager->getVirtualAddress();
	if (RamPos % 4)
	{
		Logger::queueError(Logger::Error,L"opcode not aligned to word boundary");
		return false;
	}

	// check immediates
	if (immediateData.primary.type != MipsImmediateType::None)
	{
		if (immediateData.primary.expression.isLoaded())
		{
			if (immediateData.primary.expression.evaluateInteger(immediateData.primary.value) == false)
			{
				Logger::queueError(Logger::Error, L"Invalid immediate expression");
				return false;
			}

			immediateData.primary.originalValue = immediateData.primary.value;
		}

		if (immediateData.primary.type == MipsImmediateType::ImmediateHalfFloat)
			immediateData.primary.value = floatToHalfFloat(immediateData.primary.originalValue);

		if (opcodeData.opcode.flags & MO_IMMALIGNED)	// immediate must be aligned
		{
			if (immediateData.primary.value % 4)
			{
				Logger::queueError(Logger::Error,L"Immediate must be word aligned");
				return false;
			}
		}

		if (opcodeData.opcode.flags & MO_NEGIMM) //negated immediate
		{
			immediateData.primary.value = -immediateData.primary.value;
		} else if (opcodeData.opcode.flags & MO_IPCA)	// absolute value >> 2
		{
			immediateData.primary.value = (immediateData.primary.value >> 2) & 0x3FFFFFF;
		} else if (opcodeData.opcode.flags & MO_IPCR)	// relative 16 bit value
		{
			int num = (int) (immediateData.primary.value-RamPos-4);
			
			if (num > 0x20000 || num < (-0x20000))
			{
				Logger::queueError(Logger::Error,L"Branch target %08X out of range",immediateData.primary.value);
				return false;
			}
			immediateData.primary.value = num >> 2;
		} else if (opcodeData.opcode.flags & (MO_RSP_HWOFFSET | MO_RSP_WOFFSET | MO_RSP_DWOFFSET | MO_RSP_QWOFFSET))
		{
			int shift = 0;

			if (opcodeData.opcode.flags & MO_RSP_HWOFFSET) shift = 1;
			else if (opcodeData.opcode.flags & MO_RSP_WOFFSET) shift = 2;
			else if (opcodeData.opcode.flags & MO_RSP_DWOFFSET) shift = 3;
			else if (opcodeData.opcode.flags & MO_RSP_QWOFFSET) shift = 4;

			if (immediateData.primary.value & (1 << shift) - 1){
				Logger::queueError(Logger::Error,L"Offset must be %d-byte aligned",1<<shift);
				return false;
			}

			immediateData.primary.value = immediateData.primary.value >> shift;
		}
		
		int immediateBits = getImmediateBits(immediateData.primary.type);
		unsigned int mask = (0xFFFFFFFF << (32-immediateBits)) >> (32-immediateBits);
		int digits = (immediateBits+3) / 4;

		if ((unsigned int)std::abs(immediateData.primary.value) > mask)
		{
			Logger::queueError(Logger::Error,L"Immediate value 0x%0*X out of range",digits,immediateData.primary.value);
			return false;
		}
<commit_msg>Small indent style fix in RSP offset code<commit_after>#include "stdafx.h"
#include "CMipsInstruction.h"
#include "Core/Common.h"
#include "Mips.h"
#include "MipsOpcodes.h"
#include "Core/FileManager.h"
#include "MipsParser.h"

CMipsInstruction::CMipsInstruction(MipsOpcodeData& opcode, MipsImmediateData& immediate, MipsRegisterData& registers)
{
	this->opcodeData = opcode;
	this->immediateData = immediate;
	this->registerData = registers;

	addNop = false;
	IgnoreLoadDelay = Mips.GetIgnoreDelay();
}

CMipsInstruction::~CMipsInstruction()
{

}

int getImmediateBits(MipsImmediateType type)
{
	switch (type)
	{
	case MipsImmediateType::Immediate5:
		return 5;
	case MipsImmediateType::Immediate7:
		return 7;
	case MipsImmediateType::Immediate8:
		return 8;
	case MipsImmediateType::Immediate16:
	case MipsImmediateType::ImmediateHalfFloat:
		return 16;
	case MipsImmediateType::Immediate20:
	case MipsImmediateType::Immediate20_0:
		return 20;
	case MipsImmediateType::Immediate26:
		return 26;
	default:
		return 0;
	}
}

// http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/Allegrex/VfpuState.java?spec=svn3676&r=3383#1196
int CMipsInstruction::floatToHalfFloat(int i)
{
	int s = ((i >> 16) & 0x00008000); // sign
	int e = ((i >> 23) & 0x000000ff) - (127 - 15); // exponent
	int f = ((i >> 0) & 0x007fffff); // fraction

	// need to handle NaNs and Inf?
	if (e <= 0) {
		if (e < -10) {
			if (s != 0) {
				// handle -0.0
				return 0x8000;
			}
			return 0;
		}
		f = (f | 0x00800000) >> (1 - e);
		return s | (f >> 13);
	} else if (e == 0xff - (127 - 15)) {
		if (f == 0) {
			// Inf
			return s | 0x7c00;
		}
		// NAN
		return s | 0x7fff;
	}

	if (e > 30) {
		// Overflow
		return s | 0x7c00;
	}

	return s | (e << 10) | (f >> 13);
}

bool CMipsInstruction::Validate()
{
	bool Result = false;

	bool previousNop = addNop;
	addNop = false;

	RamPos = g_fileManager->getVirtualAddress();
	if (RamPos % 4)
	{
		Logger::queueError(Logger::Error,L"opcode not aligned to word boundary");
		return false;
	}

	// check immediates
	if (immediateData.primary.type != MipsImmediateType::None)
	{
		if (immediateData.primary.expression.isLoaded())
		{
			if (immediateData.primary.expression.evaluateInteger(immediateData.primary.value) == false)
			{
				Logger::queueError(Logger::Error, L"Invalid immediate expression");
				return false;
			}

			immediateData.primary.originalValue = immediateData.primary.value;
		}

		if (immediateData.primary.type == MipsImmediateType::ImmediateHalfFloat)
			immediateData.primary.value = floatToHalfFloat(immediateData.primary.originalValue);

		if (opcodeData.opcode.flags & MO_IMMALIGNED)	// immediate must be aligned
		{
			if (immediateData.primary.value % 4)
			{
				Logger::queueError(Logger::Error,L"Immediate must be word aligned");
				return false;
			}
		}

		if (opcodeData.opcode.flags & MO_NEGIMM) 		// negated immediate
		{
			immediateData.primary.value = -immediateData.primary.value;
		} else if (opcodeData.opcode.flags & MO_IPCA)	// absolute value >> 2
		{
			immediateData.primary.value = (immediateData.primary.value >> 2) & 0x3FFFFFF;
		} else if (opcodeData.opcode.flags & MO_IPCR)	// relative 16 bit value
		{
			int num = (int) (immediateData.primary.value-RamPos-4);
			
			if (num > 0x20000 || num < (-0x20000))
			{
				Logger::queueError(Logger::Error,L"Branch target %08X out of range",immediateData.primary.value);
				return false;
			}
			immediateData.primary.value = num >> 2;
		} else if (opcodeData.opcode.flags & (MO_RSP_HWOFFSET | MO_RSP_WOFFSET | MO_RSP_DWOFFSET | MO_RSP_QWOFFSET))
		{
			int shift = 0;

			if (opcodeData.opcode.flags & MO_RSP_HWOFFSET) shift = 1;
			else if (opcodeData.opcode.flags & MO_RSP_WOFFSET) shift = 2;
			else if (opcodeData.opcode.flags & MO_RSP_DWOFFSET) shift = 3;
			else if (opcodeData.opcode.flags & MO_RSP_QWOFFSET) shift = 4;

			if (immediateData.primary.value & (1 << shift) - 1)
			{
				Logger::queueError(Logger::Error,L"Offset must be %d-byte aligned",1<<shift);
				return false;
			}
			immediateData.primary.value = immediateData.primary.value >> shift;
		}
		
		int immediateBits = getImmediateBits(immediateData.primary.type);
		unsigned int mask = (0xFFFFFFFF << (32-immediateBits)) >> (32-immediateBits);
		int digits = (immediateBits+3) / 4;

		if ((unsigned int)std::abs(immediateData.primary.value) > mask)
		{
			Logger::queueError(Logger::Error,L"Immediate value 0x%0*X out of range",digits,immediateData.primary.value);
			return false;
		}

{'fraction_non_alphanumeric': 0.13650580875781948, 'fraction_numerical': 0.03395889186773905, 'mean_word_length': 3.9518805309734515, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3843479', 'n_tokens_mistral': 3778, 'n_tokens_neox': 3275, 'n_words': 673}