project64/Source/Project64-rsp-core/Recompiler/RspAssembler.cpp

272 lines
7.3 KiB
C++

#if defined(__amd64__) || defined(_M_X64)
#include "RspAssembler.h"
#include <Common/StdString.h>
#include <Project64-rsp-core/Settings/RspSettings.h>
#include <Settings/Settings.h>
RspAssembler::RspAssembler(asmjit::CodeHolder * CodeHolder, std::string & CodeLog) :
asmjit::x86::Assembler(CodeHolder),
m_CodeLog(CodeLog)
{
setLogger(nullptr);
setErrorHandler(this);
addFlags(asmjit::FormatFlags::kHexOffsets);
addFlags(asmjit::FormatFlags::kHexImms);
addFlags(asmjit::FormatFlags::kExplainImms);
}
void RspAssembler::handleError(asmjit::Error /*err*/, const char * /*message*/, asmjit::BaseEmitter * /*origin*/)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
asmjit::Error RspAssembler::_log(const char * data, size_t size) noexcept
{
stdstr AsmjitLog(std::string(data, size));
AsmjitLog.Trim("\n");
std::string::size_type Pos = AsmjitLog.find("0x");
if (m_NumberSymbols.size() > 0 && Pos != std::string::npos)
{
uint32_t Value = 0;
for (int i = 0; i < 8; i++)
{
char c = AsmjitLog[Pos + 2 + i];
if (c >= '0' && c <= '9')
{
Value = (Value << 4) | (c - '0');
}
else if (c >= 'a' && c <= 'f')
{
Value = (Value << 4) | (c - 'a' + 10);
}
else if (c >= 'A' && c <= 'F')
{
Value = (Value << 4) | (c - 'A' + 10);
}
else
{
break;
}
}
NumberSymbolMap::iterator itr = m_NumberSymbols.find(Value);
if (itr != m_NumberSymbols.end())
{
std::string::size_type endPos = Pos + 2;
for (std::string::size_type LenSize = AsmjitLog.length(); (endPos < LenSize && isxdigit((unsigned char)AsmjitLog[endPos])); endPos++)
{
}
std::string hexStr = AsmjitLog.substr(Pos, endPos - Pos);
AsmjitLog.replace(Pos, hexStr.length(), itr->second.Symbol);
itr->second.Count -= 1;
if (itr->second.Count == 0)
{
m_NumberSymbols.erase(itr);
}
}
}
Pos = AsmjitLog.find("L");
if (m_LabelSymbols.size() > 0 && Pos != std::string::npos)
{
size_t len = AsmjitLog.length();
uint32_t Value = 0, valueLen = 0;
for (int i = 0; i < 8 && (Pos + 1 + i) < len; i++)
{
char c = AsmjitLog[Pos + 1 + i];
if (c >= '0' && c <= '9')
{
Value = (Value * 10) + (c - '0');
valueLen += 1;
}
else
{
break;
}
}
if (valueLen > 0)
{
LabelSymbolMap::iterator itr = m_LabelSymbols.find(Value);
if (itr != m_LabelSymbols.end())
{
std::string::size_type endPos = Pos + 1;
for (std::string::size_type LenSize = AsmjitLog.length(); (endPos < LenSize && isdigit((unsigned char)AsmjitLog[endPos])); endPos++)
{
}
std::string LabelStr = AsmjitLog.substr(Pos, endPos - Pos);
AsmjitLog.replace(Pos, LabelStr.length(), itr->second);
}
}
}
m_CodeLog.append(stdstr_f(" %s\n", AsmjitLog.c_str()));
return asmjit::kErrorOk;
}
void RspAssembler::Reset(void)
{
setLogger(LogAsmCode ? this : nullptr);
}
void RspAssembler::CallFunc(void * FunctPtr, const char * FunctName)
{
if (LogAsmCode)
{
AddNumberSymbol((uint64_t)FunctPtr, FunctName);
}
mov(asmjit::x86::r11, (uint64_t)FunctPtr);
call(asmjit::x86::r11);
}
#ifdef _MSC_VER
void RspAssembler::CallThis(void * ThisPtr, void * FunctPtr, const char * FunctName)
{
mov(asmjit::x86::rcx, ThisPtr);
CallFunc(FunctPtr, FunctName);
}
#else
void CX86Ops::CallThis(uint64_t ThisPtr, uint64_t FunctPtr, const char * FunctName)
{
mov(asmjit::x86::rdi, ThisPtr);
CallFunc(FunctPtr, FunctName);
}
#endif
void RspAssembler::CompConstToVariable(void * Variable, const char * VariableName, uint32_t Const)
{
if (LogAsmCode)
{
AddNumberSymbol((uint64_t)Variable, VariableName);
}
cmp(asmjit::x86::dword_ptr((uint64_t)Variable), Const);
}
void RspAssembler::CompX86regToVariable(void * Variable, const char * VariableName, const asmjit::x86::Gp & Reg)
{
if (LogAsmCode)
{
AddNumberSymbol((uint64_t)Variable, VariableName);
}
cmp(Reg, asmjit::x86::dword_ptr((uint64_t)Variable));
}
void RspAssembler::JeLabel(const char * LabelName, asmjit::Label & JumpLabel)
{
if (LogAsmCode)
{
AddLabelSymbol(JumpLabel, LabelName);
}
je(JumpLabel);
}
void RspAssembler::JgLabel(const char * LabelName, asmjit::Label & JumpLabel)
{
if (LogAsmCode)
{
AddLabelSymbol(JumpLabel, LabelName);
}
jg(JumpLabel);
}
void RspAssembler::JleLabel(const char * LabelName, asmjit::Label & JumpLabel)
{
if (LogAsmCode)
{
AddLabelSymbol(JumpLabel, LabelName);
}
jle(JumpLabel);
}
void RspAssembler::JmpLabel(const char * LabelName, asmjit::Label & JumpLabel)
{
if (LogAsmCode)
{
AddLabelSymbol(JumpLabel, LabelName);
}
jmp(JumpLabel);
}
void RspAssembler::JneLabel(const char * LabelName, asmjit::Label & JumpLabel)
{
if (LogAsmCode)
{
AddLabelSymbol(JumpLabel, LabelName);
}
jne(JumpLabel);
}
void RspAssembler::MoveConstToVariable(void * Variable, const char * VariableName, uint32_t Const)
{
if (LogAsmCode)
{
AddNumberSymbol((uint64_t)Variable, VariableName);
}
uint64_t addr = (uint64_t)Variable;
if (addr <= 0x7FFFFFFF)
{
mov(asmjit::x86::dword_ptr(addr), Const);
}
else
{
mov(asmjit::x86::r11, addr);
mov(asmjit::x86::dword_ptr(asmjit::x86::r11), Const);
}
}
void RspAssembler::MoveVariableToX86reg(const asmjit::x86::Gp & Reg, void * Variable, const char * VariableName)
{
if (LogAsmCode)
{
AddNumberSymbol((uint64_t)Variable, VariableName);
}
mov(Reg, asmjit::x86::dword_ptr((uint64_t)Variable));
}
void RspAssembler::MoveX86regToVariable(void * Variable, const char * VariableName, const asmjit::x86::Gp & Reg)
{
if (LogAsmCode)
{
AddNumberSymbol((uint64_t)Variable, VariableName);
}
mov(asmjit::x86::dword_ptr((uint64_t)(Variable)), Reg);
}
void RspAssembler::SetgVariable(void * Variable, const char * VariableName)
{
if (LogAsmCode)
{
AddNumberSymbol((uint64_t)Variable, VariableName);
}
setg(asmjit::x86::byte_ptr((uint64_t)Variable));
}
void RspAssembler::SetzVariable(void * Variable, const char * VariableName)
{
if (LogAsmCode)
{
AddNumberSymbol((uint64_t)Variable, VariableName);
}
setz(asmjit::x86::byte_ptr((uint64_t)Variable));
}
void RspAssembler::AddLabelSymbol(const asmjit::Label & Label, const char * Symbol)
{
LabelSymbolMap::iterator itr = m_LabelSymbols.find(Label.id());
if (itr == m_LabelSymbols.end())
{
m_LabelSymbols.emplace(std::make_pair(Label.id(), Symbol));
}
}
void RspAssembler::AddNumberSymbol(uint64_t Value, const char * Symbol)
{
NumberSymbolMap::iterator itr = m_NumberSymbols.find(Value);
if (itr != m_NumberSymbols.end())
{
itr->second.Count += 1;
}
else
{
m_NumberSymbols.emplace(std::make_pair(Value, NumberSymbol{Symbol, 1}));
}
}
#endif