mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-02 02:52:30 +02:00
Merge pull request #5486 from sepalani/hle-print
HLE: More printf logs added
This commit is contained in:
commit
065c3d78b7
@ -72,6 +72,7 @@ set(SRCS
|
||||
HLE/HLE.cpp
|
||||
HLE/HLE_Misc.cpp
|
||||
HLE/HLE_OS.cpp
|
||||
HLE/HLE_VarArgs.cpp
|
||||
HW/AudioInterface.cpp
|
||||
HW/CPU.cpp
|
||||
HW/DSP.cpp
|
||||
|
@ -100,6 +100,7 @@
|
||||
<ClCompile Include="HLE\HLE.cpp" />
|
||||
<ClCompile Include="HLE\HLE_Misc.cpp" />
|
||||
<ClCompile Include="HLE\HLE_OS.cpp" />
|
||||
<ClCompile Include="HLE\HLE_VarArgs.cpp" />
|
||||
<ClCompile Include="HotkeyManager.cpp" />
|
||||
<ClCompile Include="HW\AudioInterface.cpp" />
|
||||
<ClCompile Include="HW\CPU.cpp" />
|
||||
@ -343,6 +344,7 @@
|
||||
<ClInclude Include="HLE\HLE.h" />
|
||||
<ClInclude Include="HLE\HLE_Misc.h" />
|
||||
<ClInclude Include="HLE\HLE_OS.h" />
|
||||
<ClInclude Include="HLE\HLE_VarArgs.h" />
|
||||
<ClInclude Include="Host.h" />
|
||||
<ClInclude Include="HotkeyManager.h" />
|
||||
<ClInclude Include="HW\AudioInterface.h" />
|
||||
|
@ -293,6 +293,9 @@
|
||||
<ClCompile Include="HLE\HLE_OS.cpp">
|
||||
<Filter>HLE</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HLE\HLE_VarArgs.cpp" />
|
||||
<Filter>HLE</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowerPC\BreakPoints.cpp">
|
||||
<Filter>PowerPC</Filter>
|
||||
</ClCompile>
|
||||
@ -955,6 +958,9 @@
|
||||
<ClInclude Include="HLE\HLE_OS.h">
|
||||
<Filter>HLE</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HLE\HLE_VarArgs.h">
|
||||
<Filter>HLE</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowerPC\CachedInterpreter\CachedInterpreter.h">
|
||||
<Filter>PowerPC\Cached Interpreter</Filter>
|
||||
</ClInclude>
|
||||
|
@ -60,8 +60,12 @@ static const SPatch OSPatches[] = {
|
||||
{"OSReport", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"vprintf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"vprintf", HLE_OS::HLE_GeneralDebugVPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"printf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"vdprintf", HLE_OS::HLE_LogVDPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"dprintf", HLE_OS::HLE_LogDPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"vfprintf", HLE_OS::HLE_LogVFPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"fprintf", HLE_OS::HLE_LogFPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"nlPrintf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG},
|
||||
{"puts", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG}, // gcc-optimized printf?
|
||||
{"___blank", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_START, HLE_TYPE_DEBUG}, // used for early init things (normally)
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
@ -9,12 +10,20 @@
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Core/HLE/HLE_OS.h"
|
||||
#include "Core/HLE/HLE_VarArgs.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
namespace HLE_OS
|
||||
{
|
||||
std::string GetStringVA(u32 strReg = 3);
|
||||
enum class ParameterType : bool
|
||||
{
|
||||
ParameterList = false,
|
||||
VariableArgumentList = true
|
||||
};
|
||||
|
||||
std::string GetStringVA(u32 str_reg = 3,
|
||||
ParameterType parameter_type = ParameterType::ParameterList);
|
||||
|
||||
void HLE_OSPanic()
|
||||
{
|
||||
@ -27,8 +36,8 @@ void HLE_OSPanic()
|
||||
NPC = LR;
|
||||
}
|
||||
|
||||
// Generalized func for just printing string pointed to by r3.
|
||||
void HLE_GeneralDebugPrint()
|
||||
// Generalized function for printing formatted string.
|
||||
void HLE_GeneralDebugPrint(ParameterType parameter_type)
|
||||
{
|
||||
std::string report_message;
|
||||
|
||||
@ -38,12 +47,12 @@ void HLE_GeneralDebugPrint()
|
||||
if (PowerPC::HostIsRAMAddress(GPR(4)))
|
||||
{
|
||||
// ___blank(void* this, const char* fmt, ...);
|
||||
report_message = GetStringVA(4);
|
||||
report_message = GetStringVA(4, parameter_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ___blank(void* this, int log_type, const char* fmt, ...);
|
||||
report_message = GetStringVA(5);
|
||||
report_message = GetStringVA(5, parameter_type);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -51,12 +60,12 @@ void HLE_GeneralDebugPrint()
|
||||
if (PowerPC::HostIsRAMAddress(GPR(3)))
|
||||
{
|
||||
// ___blank(const char* fmt, ...);
|
||||
report_message = GetStringVA();
|
||||
report_message = GetStringVA(3, parameter_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ___blank(int log_type, const char* fmt, ...);
|
||||
report_message = GetStringVA(4);
|
||||
report_message = GetStringVA(4, parameter_type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,6 +74,18 @@ void HLE_GeneralDebugPrint()
|
||||
NOTICE_LOG(OSREPORT, "%08x->%08x| %s", LR, PC, SHIFTJISToUTF8(report_message).c_str());
|
||||
}
|
||||
|
||||
// Generalized function for printing formatted string using parameter list.
|
||||
void HLE_GeneralDebugPrint()
|
||||
{
|
||||
HLE_GeneralDebugPrint(ParameterType::ParameterList);
|
||||
}
|
||||
|
||||
// Generalized function for printing formatted string using va_list.
|
||||
void HLE_GeneralDebugVPrint()
|
||||
{
|
||||
HLE_GeneralDebugPrint(ParameterType::VariableArgumentList);
|
||||
}
|
||||
|
||||
// __write_console(int fd, const void* buffer, const u32* size)
|
||||
void HLE_write_console()
|
||||
{
|
||||
@ -89,14 +110,79 @@ void HLE_write_console()
|
||||
NOTICE_LOG(OSREPORT, "%08x->%08x| %s", LR, PC, SHIFTJISToUTF8(report_message).c_str());
|
||||
}
|
||||
|
||||
std::string GetStringVA(u32 strReg)
|
||||
// Log (v)dprintf message if fd is 1 (stdout) or 2 (stderr)
|
||||
void HLE_LogDPrint(ParameterType parameter_type)
|
||||
{
|
||||
NPC = LR;
|
||||
|
||||
if (GPR(3) != 1 && GPR(3) != 2)
|
||||
return;
|
||||
|
||||
std::string report_message = GetStringVA(4, parameter_type);
|
||||
NOTICE_LOG(OSREPORT, "%08x->%08x| %s", LR, PC, SHIFTJISToUTF8(report_message).c_str());
|
||||
}
|
||||
|
||||
// Log dprintf message
|
||||
// -> int dprintf(int fd, const char* format, ...);
|
||||
void HLE_LogDPrint()
|
||||
{
|
||||
HLE_LogDPrint(ParameterType::ParameterList);
|
||||
}
|
||||
|
||||
// Log vdprintf message
|
||||
// -> int vdprintf(int fd, const char* format, va_list ap);
|
||||
void HLE_LogVDPrint()
|
||||
{
|
||||
HLE_LogDPrint(ParameterType::VariableArgumentList);
|
||||
}
|
||||
|
||||
// Log (v)fprintf message if FILE is stdout or stderr
|
||||
void HLE_LogFPrint(ParameterType parameter_type)
|
||||
{
|
||||
NPC = LR;
|
||||
|
||||
// The structure FILE is implementation defined.
|
||||
// Both libogc and Dolphin SDK seem to store the fd at the same address.
|
||||
int fd = -1;
|
||||
if (PowerPC::HostIsRAMAddress(GPR(3)) && PowerPC::HostIsRAMAddress(GPR(3) + 0xF))
|
||||
{
|
||||
// The fd is stored as a short at FILE+0xE.
|
||||
fd = static_cast<short>(PowerPC::HostRead_U16(GPR(3) + 0xE));
|
||||
}
|
||||
if (fd != 1 && fd != 2)
|
||||
{
|
||||
// On RVL SDK it seems stored at FILE+0x2.
|
||||
fd = static_cast<short>(PowerPC::HostRead_U16(GPR(3) + 0x2));
|
||||
}
|
||||
if (fd != 1 && fd != 2)
|
||||
return;
|
||||
|
||||
std::string report_message = GetStringVA(4, parameter_type);
|
||||
NOTICE_LOG(OSREPORT, "%08x->%08x| %s", LR, PC, SHIFTJISToUTF8(report_message).c_str());
|
||||
}
|
||||
|
||||
// Log fprintf message
|
||||
// -> int fprintf(FILE* stream, const char* format, ...);
|
||||
void HLE_LogFPrint()
|
||||
{
|
||||
HLE_LogFPrint(ParameterType::ParameterList);
|
||||
}
|
||||
|
||||
// Log vfprintf message
|
||||
// -> int vfprintf(FILE* stream, const char* format, va_list ap);
|
||||
void HLE_LogVFPrint()
|
||||
{
|
||||
HLE_LogFPrint(ParameterType::VariableArgumentList);
|
||||
}
|
||||
|
||||
std::string GetStringVA(u32 str_reg, ParameterType parameter_type)
|
||||
{
|
||||
std::string ArgumentBuffer;
|
||||
u32 ParameterCounter = strReg + 1;
|
||||
u32 FloatingParameterCounter = 1;
|
||||
|
||||
std::string result;
|
||||
std::string string = PowerPC::HostGetString(GPR(strReg));
|
||||
std::string string = PowerPC::HostGetString(GPR(str_reg));
|
||||
auto ap = parameter_type == ParameterType::VariableArgumentList ?
|
||||
std::make_unique<HLE::SystemVABI::VAListStruct>(GPR(str_reg + 1)) :
|
||||
std::make_unique<HLE::SystemVABI::VAList>(GPR(1) + 0x8, str_reg + 1);
|
||||
|
||||
for (size_t i = 0; i < string.size(); i++)
|
||||
{
|
||||
@ -120,38 +206,13 @@ std::string GetStringVA(u32 strReg)
|
||||
|
||||
ArgumentBuffer += string[i];
|
||||
|
||||
u64 Parameter;
|
||||
if (ParameterCounter > 10)
|
||||
{
|
||||
Parameter = PowerPC::HostRead_U32(GPR(1) + 0x8 + ((ParameterCounter - 11) * 4));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string[i - 1] == 'l' &&
|
||||
string[i - 2] == 'l') // hax, just seen this on sysmenu osreport
|
||||
{
|
||||
Parameter = GPR(++ParameterCounter);
|
||||
Parameter = (Parameter << 32) | GPR(++ParameterCounter);
|
||||
}
|
||||
else // normal, 32bit
|
||||
Parameter = GPR(ParameterCounter);
|
||||
}
|
||||
ParameterCounter++;
|
||||
|
||||
switch (string[i])
|
||||
{
|
||||
case 's':
|
||||
result += StringFromFormat(ArgumentBuffer.c_str(),
|
||||
PowerPC::HostGetString((u32)Parameter).c_str());
|
||||
PowerPC::HostGetString(ap->GetArgT<u32>()).c_str());
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
{
|
||||
result += StringFromFormat(ArgumentBuffer.c_str(), Parameter);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
@ -160,25 +221,24 @@ std::string GetStringVA(u32 strReg)
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
{
|
||||
result += StringFromFormat(ArgumentBuffer.c_str(), rPS0(FloatingParameterCounter));
|
||||
FloatingParameterCounter++;
|
||||
ParameterCounter--;
|
||||
result += StringFromFormat(ArgumentBuffer.c_str(), ap->GetArgT<double>());
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
// Override, so 64bit Dolphin prints 32bit pointers, since the ppc is 32bit :)
|
||||
result += StringFromFormat("%x", (u32)Parameter);
|
||||
result += StringFromFormat("%x", ap->GetArgT<u32>());
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
PowerPC::HostWrite_U32(static_cast<u32>(result.size()), static_cast<u32>(Parameter));
|
||||
// %n doesn't output anything, so the result variable is untouched
|
||||
PowerPC::HostWrite_U32(static_cast<u32>(result.size()), ap->GetArgT<u32>());
|
||||
break;
|
||||
|
||||
default:
|
||||
result += StringFromFormat(ArgumentBuffer.c_str(), Parameter);
|
||||
if (string[i - 1] == 'l' && string[i - 2] == 'l')
|
||||
result += StringFromFormat(ArgumentBuffer.c_str(), ap->GetArgT<u64>());
|
||||
else
|
||||
result += StringFromFormat(ArgumentBuffer.c_str(), ap->GetArgT<u32>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,11 @@
|
||||
namespace HLE_OS
|
||||
{
|
||||
void HLE_GeneralDebugPrint();
|
||||
void HLE_GeneralDebugVPrint();
|
||||
void HLE_write_console();
|
||||
void HLE_OSPanic();
|
||||
void HLE_LogDPrint();
|
||||
void HLE_LogVDPrint();
|
||||
void HLE_LogFPrint();
|
||||
void HLE_LogVFPrint();
|
||||
}
|
||||
|
67
Source/Core/Core/HLE/HLE_VarArgs.cpp
Normal file
67
Source/Core/Core/HLE/HLE_VarArgs.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Core/HLE/HLE_VarArgs.h"
|
||||
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
HLE::SystemVABI::VAList::~VAList() = default;
|
||||
|
||||
u32 HLE::SystemVABI::VAList::GetGPR(u32 gpr) const
|
||||
{
|
||||
return GPR(gpr);
|
||||
}
|
||||
|
||||
double HLE::SystemVABI::VAList::GetFPR(u32 fpr) const
|
||||
{
|
||||
return rPS0(fpr);
|
||||
}
|
||||
|
||||
HLE::SystemVABI::VAListStruct::VAListStruct(u32 address)
|
||||
: VAList(0), m_va_list{PowerPC::HostRead_U8(address), PowerPC::HostRead_U8(address + 1),
|
||||
PowerPC::HostRead_U32(address + 4), PowerPC::HostRead_U32(address + 8)},
|
||||
m_address(address), m_has_fpr_area(GetCRBit(6) == 1)
|
||||
{
|
||||
m_stack = m_va_list.overflow_arg_area;
|
||||
m_gpr += m_va_list.gpr;
|
||||
m_fpr += m_va_list.fpr;
|
||||
}
|
||||
|
||||
u32 HLE::SystemVABI::VAListStruct::GetGPRArea() const
|
||||
{
|
||||
return m_va_list.reg_save_area;
|
||||
}
|
||||
|
||||
u32 HLE::SystemVABI::VAListStruct::GetFPRArea() const
|
||||
{
|
||||
return GetGPRArea() + 4 * 8;
|
||||
}
|
||||
|
||||
u32 HLE::SystemVABI::VAListStruct::GetGPR(u32 gpr) const
|
||||
{
|
||||
if (gpr < 3 || gpr > 10)
|
||||
{
|
||||
ERROR_LOG(OSHLE, "VAListStruct at %08x doesn't have GPR%d!", m_address, gpr);
|
||||
return 0;
|
||||
}
|
||||
const u32 gpr_address = Common::AlignUp(GetGPRArea() + 4 * (gpr - 3), 4);
|
||||
return PowerPC::HostRead_U32(gpr_address);
|
||||
}
|
||||
|
||||
double HLE::SystemVABI::VAListStruct::GetFPR(u32 fpr) const
|
||||
{
|
||||
double value = 0.0;
|
||||
|
||||
if (!m_has_fpr_area || fpr < 1 || fpr > 8)
|
||||
{
|
||||
ERROR_LOG(OSHLE, "VAListStruct at %08x doesn't have FPR%d!", m_address, fpr);
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 fpr_address = Common::AlignUp(GetFPRArea() + 8 * (fpr - 1), 8);
|
||||
const u64 integral = PowerPC::HostRead_U64(fpr_address);
|
||||
std::memcpy(&value, &integral, sizeof(double));
|
||||
}
|
||||
return value;
|
||||
}
|
177
Source/Core/Core/HLE/HLE_VarArgs.h
Normal file
177
Source/Core/Core/HLE/HLE_VarArgs.h
Normal file
@ -0,0 +1,177 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/Align.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace HLE
|
||||
{
|
||||
namespace SystemVABI
|
||||
{
|
||||
// SFINAE
|
||||
template <typename T>
|
||||
constexpr bool IS_ARG_POINTER = std::is_union<T>() || std::is_class<T>();
|
||||
template <typename T>
|
||||
constexpr bool IS_WORD = std::is_pointer<T>() || (std::is_integral<T>() && sizeof(T) <= 4);
|
||||
template <typename T>
|
||||
constexpr bool IS_DOUBLE_WORD = std::is_integral<T>() && sizeof(T) == 8;
|
||||
template <typename T>
|
||||
constexpr bool IS_ARG_REAL = std::is_floating_point<T>();
|
||||
|
||||
// See System V ABI (SVR4) for more details
|
||||
// -> 3-18 Parameter Passing
|
||||
// -> 3-21 Variable Argument Lists
|
||||
//
|
||||
// Source:
|
||||
// http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
|
||||
class VAList
|
||||
{
|
||||
public:
|
||||
explicit VAList(u32 stack, u32 gpr = 3, u32 fpr = 1, u32 gpr_max = 10, u32 fpr_max = 8)
|
||||
: m_gpr(gpr), m_fpr(fpr), m_gpr_max(gpr_max), m_fpr_max(fpr_max), m_stack(stack)
|
||||
{
|
||||
}
|
||||
virtual ~VAList();
|
||||
|
||||
// 0 - arg_ARGPOINTER
|
||||
template <typename T, typename std::enable_if_t<IS_ARG_POINTER<T>>* = nullptr>
|
||||
T GetArg()
|
||||
{
|
||||
T obj;
|
||||
u32 addr = GetArg<u32>();
|
||||
|
||||
for (size_t i = 0; i < sizeof(T); i += 1, addr += 1)
|
||||
{
|
||||
reinterpret_cast<u8*>(&obj)[i] = PowerPC::HostRead_U8(addr);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
// 1 - arg_WORD
|
||||
template <typename T, typename std::enable_if_t<IS_WORD<T>>* = nullptr>
|
||||
T GetArg()
|
||||
{
|
||||
static_assert(!std::is_pointer<T>(), "VAList doesn't support pointers");
|
||||
u64 value;
|
||||
|
||||
if (m_gpr <= m_gpr_max)
|
||||
{
|
||||
value = GetGPR(m_gpr);
|
||||
m_gpr += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stack = Common::AlignUp(m_stack, 4);
|
||||
value = PowerPC::HostRead_U32(m_stack);
|
||||
m_stack += 4;
|
||||
}
|
||||
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
|
||||
// 2 - arg_DOUBLEWORD
|
||||
template <typename T, typename std::enable_if_t<IS_DOUBLE_WORD<T>>* = nullptr>
|
||||
T GetArg()
|
||||
{
|
||||
u64 value;
|
||||
|
||||
if (m_gpr % 2 == 0)
|
||||
m_gpr += 1;
|
||||
if (m_gpr < m_gpr_max)
|
||||
{
|
||||
value = static_cast<u64>(GetGPR(m_gpr)) << 32 | GetGPR(m_gpr + 1);
|
||||
m_gpr += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stack = Common::AlignUp(m_stack, 8);
|
||||
value = PowerPC::HostRead_U64(m_stack);
|
||||
m_stack += 8;
|
||||
}
|
||||
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
|
||||
// 3 - arg_ARGREAL
|
||||
template <typename T, typename std::enable_if_t<IS_ARG_REAL<T>>* = nullptr>
|
||||
T GetArg()
|
||||
{
|
||||
double value;
|
||||
|
||||
if (m_fpr <= m_fpr_max)
|
||||
{
|
||||
value = GetFPR(m_fpr);
|
||||
m_fpr += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stack = Common::AlignUp(m_stack, 8);
|
||||
const u64 integral = PowerPC::HostRead_U64(m_stack);
|
||||
std::memcpy(&value, &integral, sizeof(double));
|
||||
m_stack += 8;
|
||||
}
|
||||
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
|
||||
// Helper
|
||||
template <typename T>
|
||||
T GetArgT()
|
||||
{
|
||||
return static_cast<T>(GetArg<T>());
|
||||
}
|
||||
|
||||
protected:
|
||||
u32 m_gpr = 3;
|
||||
u32 m_fpr = 1;
|
||||
const u32 m_gpr_max = 10;
|
||||
const u32 m_fpr_max = 8;
|
||||
u32 m_stack;
|
||||
|
||||
private:
|
||||
virtual u32 GetGPR(u32 gpr) const;
|
||||
virtual double GetFPR(u32 fpr) const;
|
||||
};
|
||||
|
||||
// See System V ABI (SVR4) for more details
|
||||
// -> 6-6 Required Routines
|
||||
// -> 3-21 Variable Argument Lists
|
||||
//
|
||||
// Source:
|
||||
// http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
|
||||
class VAListStruct : public VAList
|
||||
{
|
||||
public:
|
||||
explicit VAListStruct(u32 address);
|
||||
~VAListStruct() = default;
|
||||
|
||||
private:
|
||||
struct svr4_va_list
|
||||
{
|
||||
u8 gpr;
|
||||
u8 fpr;
|
||||
u32 overflow_arg_area;
|
||||
u32 reg_save_area;
|
||||
};
|
||||
const svr4_va_list m_va_list;
|
||||
const u32 m_address;
|
||||
const bool m_has_fpr_area;
|
||||
|
||||
u32 GetGPRArea() const;
|
||||
u32 GetFPRArea() const;
|
||||
|
||||
u32 GetGPR(u32 gpr) const override;
|
||||
double GetFPR(u32 fpr) const override;
|
||||
};
|
||||
|
||||
} // namespace SystemVABI
|
||||
} // namespace HLE
|
Loading…
Reference in New Issue
Block a user