CB_FUNC/SC_FUNC fixed

This commit is contained in:
Nekotekina 2015-01-07 19:44:47 +03:00
parent a1b1f6be63
commit bd71c1200e
6 changed files with 157 additions and 77 deletions

View file

@ -475,6 +475,7 @@ namespace psv_func_detail
static __forceinline void func(ARMv7Thread& CPU, T result) static __forceinline void func(ARMv7Thread& CPU, T result)
{ {
CPU.GPR[0] = 0; // TODO
(T&)CPU.GPR[0] = result; (T&)CPU.GPR[0] = result;
} }
}; };

View file

@ -811,4 +811,89 @@ public:
cpu_thread& args(std::initializer_list<std::string> values) override; cpu_thread& args(std::initializer_list<std::string> values) override;
cpu_thread& run() override; cpu_thread& run() override;
ppu_thread& gpr(uint index, u64 value); ppu_thread& gpr(uint index, u64 value);
}; };
template<typename T, size_t size = sizeof(T)>
struct cast_ppu_gpr
{
static_assert(sizeof(T) <= 8, "Type for cast_ppu_gpr is invalid (too big)");
static u64 func(const T& value)
{
u64 result = 0;
(T&)result = value;
return result;
}
};
template<typename T>
struct cast_ppu_gpr<T, 1>
{
static u64 func(const T& value)
{
return (u8&)value;
}
};
template<typename T>
struct cast_ppu_gpr<T, 2>
{
static u64 func(const T& value)
{
return (u16&)value;
}
};
template<typename T>
struct cast_ppu_gpr<T, 4>
{
static u64 func(const T& value)
{
return (u32&)value;
}
};
template<typename T>
struct cast_ppu_gpr<T, 8>
{
static u64 func(const T& value)
{
return (u64&)value;
}
};
template<>
struct cast_ppu_gpr<s8, 1>
{
static u64 func(const s8& value)
{
return value;
}
};
template<>
struct cast_ppu_gpr<s16, 2>
{
static u64 func(const s16& value)
{
return value;
}
};
template<>
struct cast_ppu_gpr<s32, 4>
{
static u64 func(const s32& value)
{
return value;
}
};
template<>
struct cast_ppu_gpr<s64, 8>
{
static u64 func(const s64& value)
{
return value;
}
};

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "Memory.h" #include "Memory.h"
class CPUThread;
namespace vm namespace vm
{ {
enum memory_location : uint enum memory_location : uint
@ -171,6 +173,9 @@ namespace vm
} }
void close(); void close();
u32 stack_push(CPUThread& CPU, u32 size, u32 align, u32& old_pos);
void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos);
} }
#include "vm_ref.h" #include "vm_ref.h"

View file

@ -1,9 +1,6 @@
#pragma once #pragma once
class CPUThread; class CPUThread;
class PPUThread;
class SPUThread;
class ARMv7Thread;
namespace vm namespace vm
{ {
@ -501,108 +498,102 @@ namespace vm
} }
}; };
u32 stack_push(CPUThread& CPU, u32 size, u32 align, u32& old_pos);
void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos);
template<typename T> template<typename T>
class stackvar class stackvar
{ {
T* m_ptr; struct stack_allocation
u32 m_addr;
u32 m_size;
u32 m_align;
u32 m_old_pos;
CPUThread& m_thread;
void alloc()
{ {
m_addr = stack_push(m_thread, m_size, m_align, m_old_pos); T* ptr;
m_ptr = vm::get_ptr<T>(m_addr); u32 addr;
} u32 size;
u32 align;
u32 old_pos;
void dealloc() stack_allocation(CPUThread& CPU, u32 size, u32 align)
{ : size(size)
if (m_addr) , align(align)
{ {
stack_pop(m_thread, m_addr, m_old_pos); addr = stack_push(CPU, size, align, old_pos);
m_addr = 0; ptr = vm::get_ptr<T>(addr);
m_ptr = vm::get_ptr<T>(0u);
} }
}
stack_allocation() = delete;
stack_allocation(const stack_allocation& r) = delete;
stack_allocation(stack_allocation&& r) = delete;
stack_allocation& operator = (const stack_allocation& r) = delete;
stack_allocation& operator = (stack_allocation&& r) = delete;
} const m_data;
CPUThread& m_thread;
public: public:
stackvar(CPUThread& CPU, u32 size = sizeof(T), u32 align = __alignof(T)) stackvar(CPUThread& CPU, u32 size = sizeof(T), u32 align = __alignof(T))
: m_size(size) : m_data(CPU, size, align)
, m_align(align)
, m_thread(CPU) , m_thread(CPU)
{ {
alloc();
} }
stackvar(const stackvar& r) stackvar(const stackvar& r)
: m_size(r.m_size) : m_data(r.m_thread, r.m_data.m_size, r.m_data.m_align)
, m_align(r.m_align)
, m_thread(r.m_thread) , m_thread(r.m_thread)
{ {
alloc(); *m_data.ptr = *r.m_data.ptr;
*m_ptr = *r.m_ptr;
} }
stackvar(stackvar&& r) stackvar(stackvar&& r) = delete;
: m_ptr(r.m_ptr)
, m_addr(r.m_addr)
, m_size(r.m_size)
, m_align(r.m_align)
, m_old_pos(r.m_old_pos)
, m_thread(r.m_thread)
{
r.m_addr = 0;
r.m_ptr = vm::get_ptr<T>(0u);
}
~stackvar() ~stackvar()
{ {
dealloc(); stack_pop(m_thread, m_data.addr, m_data.old_pos);
} }
stackvar& operator = (const stackvar& r)
{
*m_data.ptr = *r.m_data.ptr;
return *this;
}
stackvar& operator = (stackvar&& r) = delete;
T* operator -> () T* operator -> ()
{ {
return m_ptr; return m_data.ptr;
} }
const T* operator -> () const const T* operator -> () const
{ {
return m_ptr; return m_data.ptr;
} }
T* get_ptr() T* get_ptr()
{ {
return m_ptr; return m_data.ptr;
} }
const T* get_ptr() const const T* get_ptr() const
{ {
return m_ptr; return m_data.ptr;
} }
T& value() T& value()
{ {
return *m_ptr; return *m_data.ptr;
} }
const T& value() const const T& value() const
{ {
return *m_ptr; return *m_data.ptr;
} }
u32 addr() const u32 addr() const
{ {
return m_addr; return m_data.addr;
} }
u32 size() const u32 size() const
{ {
return m_size; return m_data.size;
} }
/* /*
@ -614,22 +605,22 @@ namespace vm
template<typename AT> operator const ps3::ptr<T, 1, AT>() const template<typename AT> operator const ps3::ptr<T, 1, AT>() const
{ {
return ps3::ptr<T, 1, AT>::make(m_addr); return ps3::ptr<T, 1, AT>::make(m_data.addr);
} }
template<typename AT> operator const ps3::ptr<const T, 1, AT>() const template<typename AT> operator const ps3::ptr<const T, 1, AT>() const
{ {
return ps3::ptr<const T, 1, AT>::make(m_addr); return ps3::ptr<const T, 1, AT>::make(m_data.addr);
} }
operator T&() operator T&()
{ {
return *m_ptr; return *m_data.ptr;
} }
operator const T&() const operator const T&() const
{ {
return *m_ptr; return *m_data.ptr;
} }
}; };
} }

View file

@ -24,9 +24,9 @@ namespace cb_detail
{ {
static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_GENERAL"); static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_GENERAL");
__forceinline static void set_value(PPUThread& CPU, const T arg) __forceinline static void set_value(PPUThread& CPU, const T& arg)
{ {
(T&)CPU.GPR[g_count + 2] = arg; CPU.GPR[g_count + 2] = cast_ppu_gpr<T>::func(arg);
} }
}; };
@ -35,7 +35,7 @@ namespace cb_detail
{ {
static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_FLOAT"); static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_FLOAT");
__forceinline static void set_value(PPUThread& CPU, const T arg) __forceinline static void set_value(PPUThread& CPU, const T& arg)
{ {
CPU.FPR[f_count] = arg; CPU.FPR[f_count] = arg;
} }
@ -46,9 +46,9 @@ namespace cb_detail
{ {
static_assert(std::is_same<T, u128>::value, "Invalid callback argument type for ARG_VECTOR"); static_assert(std::is_same<T, u128>::value, "Invalid callback argument type for ARG_VECTOR");
__forceinline static void set_value(PPUThread& CPU, const T arg) __forceinline static void set_value(PPUThread& CPU, const T& arg)
{ {
(T&)CPU.VPR[v_count + 1] = arg; CPU.VPR[v_count + 1] = arg;
} }
}; };
@ -59,13 +59,11 @@ namespace cb_detail
static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)");
static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_STACK"); static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_STACK");
__forceinline static void set_value(PPUThread& CPU, const T arg) __forceinline static void set_value(PPUThread& CPU, const T& arg)
{ {
const int stack_pos = 0x70 + (g_count - 9) * 8 - FIXED_STACK_FRAME_SIZE; const int stack_pos = 0x70 + (g_count - 9) * 8 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)"); static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)");
u64 value = 0; vm::write64(CPU.GPR[1] + stack_pos, cast_ppu_gpr<T>::func(arg));
(T&)value = arg;
vm::write64(CPU.GPR[1] + stack_pos, value);
} }
}; };
@ -121,11 +119,11 @@ namespace cb_detail
template<typename T> template<typename T>
struct _func_res<T, ARG_VECTOR> struct _func_res<T, ARG_VECTOR>
{ {
static_assert(sizeof(T) == 16, "Invalid callback result type for ARG_VECTOR"); static_assert(std::is_same<T, u128>::value, "Invalid callback result type for ARG_VECTOR");
__forceinline static T get_value(const PPUThread& CPU) __forceinline static T get_value(const PPUThread& CPU)
{ {
return (T&)CPU.VPR[2]; return CPU.VPR[2];
} }
}; };
@ -167,8 +165,8 @@ namespace vm
template<typename AT, typename RT, typename... T> template<typename AT, typename RT, typename... T>
__forceinline RT _ptr_base<RT(*)(T...), 1, AT>::call(CPUThread& CPU, T... args) const __forceinline RT _ptr_base<RT(*)(T...), 1, AT>::call(CPUThread& CPU, T... args) const
{ {
const u32 pc = vm::get_ref<be_t<u32>>(m_addr); const u32 pc = vm::get_ref<be_t<u32>>((u32)m_addr);
const u32 rtoc = vm::get_ref<be_t<u32>>(m_addr + 4); const u32 rtoc = vm::get_ref<be_t<u32>>((u32)m_addr + 4);
return cb_detail::_func_caller<RT, T...>::call(static_cast<PPUThread&>(CPU), pc, rtoc, args...); return cb_detail::_func_caller<RT, T...>::call(static_cast<PPUThread&>(CPU), pc, rtoc, args...);
} }

View file

@ -46,11 +46,11 @@ namespace detail
template<typename T, int g_count, int f_count, int v_count> template<typename T, int g_count, int f_count, int v_count>
struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count> struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count>
{ {
static_assert(sizeof(T) == 16, "Invalid function argument type for ARG_VECTOR"); static_assert(std::is_same<T, u128>::value, "Invalid function argument type for ARG_VECTOR");
static __forceinline T func(PPUThread& CPU) static __forceinline T func(PPUThread& CPU)
{ {
return (T&)CPU.VPR[v_count + 1]; return CPU.VPR[v_count + 1];
} }
}; };
@ -75,9 +75,9 @@ namespace detail
static_assert(type == ARG_GENERAL, "Wrong use of bind_result template"); static_assert(type == ARG_GENERAL, "Wrong use of bind_result template");
static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_GENERAL"); static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_GENERAL");
static __forceinline void func(PPUThread& CPU, T result) static __forceinline void func(PPUThread& CPU, const T& result)
{ {
(T&)CPU.GPR[3] = result; CPU.GPR[3] = cast_ppu_gpr<T>::func(result);
} }
}; };
@ -86,7 +86,7 @@ namespace detail
{ {
static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT"); static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT");
static __forceinline void func(PPUThread& CPU, T result) static __forceinline void func(PPUThread& CPU, const T& result)
{ {
CPU.FPR[1] = (double)result; CPU.FPR[1] = (double)result;
} }
@ -95,11 +95,11 @@ namespace detail
template<typename T> template<typename T>
struct bind_result<T, ARG_VECTOR> struct bind_result<T, ARG_VECTOR>
{ {
static_assert(sizeof(T) == 16, "Invalid function result type for ARG_VECTOR"); static_assert(std::is_same<T, u128>::value, "Invalid function result type for ARG_VECTOR");
static __forceinline void func(PPUThread& CPU, const T result) static __forceinline void func(PPUThread& CPU, const T& result)
{ {
(T&)CPU.VPR[2] = result; CPU.VPR[2] = result;
} }
}; };