HLE: SVR4 VAList struct added

This commit is contained in:
Sepalani 2017-01-28 03:28:28 +00:00
parent 5a4f085c10
commit 061dadbc61
2 changed files with 84 additions and 1 deletions

View File

@ -4,6 +4,8 @@
#include "Core/HLE/HLE_VarArgs.h"
#include "Common/Logging/Log.h"
HLE::SystemVABI::VAList::~VAList() = default;
u32 HLE::SystemVABI::VAList::GetGPR(u32 gpr) const
@ -15,3 +17,51 @@ 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;
}

View File

@ -130,15 +130,48 @@ public:
return static_cast<T>(GetArg<T>());
}
private:
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