mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-08 17:50:31 +01:00
340 lines
5.4 KiB
C++
340 lines
5.4 KiB
C++
#pragma once
|
|
#include "Emu/CPU/CPUThread.h"
|
|
#include "Emu/Memory/Memory.h"
|
|
|
|
enum ARMv7InstructionSet
|
|
{
|
|
ARM,
|
|
Thumb,
|
|
Jazelle,
|
|
ThumbEE
|
|
};
|
|
|
|
class ARMv7Thread : public CPUThread
|
|
{
|
|
public:
|
|
u32 m_arg;
|
|
u8 m_last_instr_size;
|
|
const char* m_last_instr_name;
|
|
|
|
ARMv7Thread();
|
|
|
|
union
|
|
{
|
|
u32 GPR[15];
|
|
|
|
struct
|
|
{
|
|
u32 pad[13];
|
|
|
|
union
|
|
{
|
|
u32 SP;
|
|
|
|
struct { u16 SP_main, SP_process; };
|
|
};
|
|
|
|
u32 LR;
|
|
};
|
|
};
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
u32 N : 1; //Negative condition code flag
|
|
u32 Z : 1; //Zero condition code flag
|
|
u32 C : 1; //Carry condition code flag
|
|
u32 V : 1; //Overflow condition code flag
|
|
u32 Q : 1; //Set to 1 if an SSAT or USAT instruction changes (saturates) the input value for the signed or unsigned range of the result
|
|
u32 : 27;
|
|
};
|
|
|
|
u32 APSR;
|
|
|
|
} APSR;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
u32 : 24;
|
|
u32 exception : 8;
|
|
};
|
|
|
|
u32 IPSR;
|
|
|
|
} IPSR;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
u32 code1 : 16;
|
|
u32 code0 : 16;
|
|
};
|
|
|
|
u32 data;
|
|
|
|
} code;
|
|
|
|
ARMv7InstructionSet ISET;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
u8 cond : 3;
|
|
u8 state : 5;
|
|
};
|
|
|
|
u8 IT;
|
|
|
|
u32 advance()
|
|
{
|
|
const u32 res = (state & 0xf) ? (cond << 1 | state >> 4) : 0xe /* true */;
|
|
|
|
state <<= 1;
|
|
if ((state & 0xf) == 0) // if no d
|
|
{
|
|
IT = 0; // clear ITSTATE
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return (state & 0xf) != 0;
|
|
}
|
|
|
|
} ITSTATE;
|
|
|
|
void write_gpr(u32 n, u32 value)
|
|
{
|
|
assert(n < 16);
|
|
|
|
if(n < 15)
|
|
{
|
|
GPR[n] = value;
|
|
}
|
|
else
|
|
{
|
|
SetBranch(value & ~1);
|
|
}
|
|
}
|
|
|
|
u32 read_gpr(u32 n)
|
|
{
|
|
assert(n < 16);
|
|
|
|
if(n < 15)
|
|
{
|
|
return GPR[n];
|
|
}
|
|
|
|
return PC;
|
|
}
|
|
|
|
void update_code(const u32 address)
|
|
{
|
|
code.code0 = vm::psv::read16(address & ~1);
|
|
code.code1 = vm::psv::read16(address + 2 & ~1);
|
|
m_arg = address & 0x1 ? code.code1 << 16 | code.code0 : code.data;
|
|
}
|
|
|
|
public:
|
|
virtual void InitRegs();
|
|
virtual void InitStack();
|
|
u32 GetStackArg(u32 pos);
|
|
void FastCall(u32 addr);
|
|
void FastStop();
|
|
virtual void DoRun();
|
|
|
|
public:
|
|
virtual std::string RegsToString();
|
|
virtual std::string ReadRegString(const std::string& reg);
|
|
virtual bool WriteRegString(const std::string& reg, std::string value);
|
|
|
|
protected:
|
|
virtual void DoReset();
|
|
virtual void DoPause();
|
|
virtual void DoResume();
|
|
virtual void DoStop();
|
|
|
|
virtual void DoCode();
|
|
};
|
|
class arm7_thread : cpu_thread
|
|
{
|
|
static const u32 stack_align = 0x10;
|
|
vm::ptr<u64> argv;
|
|
u32 argc;
|
|
vm::ptr<u64> envp;
|
|
|
|
public:
|
|
arm7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
|
|
|
|
cpu_thread& args(std::initializer_list<std::string> values) override
|
|
{
|
|
if (!values.size())
|
|
return *this;
|
|
|
|
//assert(argc == 0);
|
|
|
|
//envp.set(vm::alloc((u32)sizeof(envp), stack_align, vm::main));
|
|
//*envp = 0;
|
|
//argv.set(vm::alloc(u32(sizeof(argv)* values.size()), stack_align, vm::main));
|
|
|
|
for (auto &arg : values)
|
|
{
|
|
//u32 arg_size = align(u32(arg.size() + 1), stack_align);
|
|
//u32 arg_addr = vm::alloc(arg_size, stack_align, vm::main);
|
|
|
|
//std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
|
|
|
|
//argv[argc++] = arg_addr;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
cpu_thread& run() override
|
|
{
|
|
thread->Run();
|
|
|
|
//static_cast<ARMv7Thread*>(thread)->GPR[0] = argc;
|
|
//static_cast<ARMv7Thread*>(thread)->GPR[1] = argv.addr();
|
|
//static_cast<ARMv7Thread*>(thread)->GPR[2] = envp.addr();
|
|
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
template<typename T, bool is_enum = std::is_enum<T>::value>
|
|
struct cast_armv7_gpr
|
|
{
|
|
static_assert(is_enum, "Invalid type for cast_armv7_gpr");
|
|
|
|
typedef typename std::underlying_type<T>::type underlying_type;
|
|
|
|
__forceinline static u32 to_gpr(const T& value)
|
|
{
|
|
return cast_armv7_gpr<underlying_type>::to_gpr(static_cast<underlying_type>(value));
|
|
}
|
|
|
|
__forceinline static T from_gpr(const u32 reg)
|
|
{
|
|
return static_cast<T>(cast_armv7_gpr<underlying_type>::from_gpr(reg));
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct cast_armv7_gpr<u8, false>
|
|
{
|
|
__forceinline static u32 to_gpr(const u8& value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
__forceinline static u8 from_gpr(const u32 reg)
|
|
{
|
|
return static_cast<u8>(reg);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct cast_armv7_gpr<u16, false>
|
|
{
|
|
__forceinline static u32 to_gpr(const u16& value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
__forceinline static u16 from_gpr(const u32 reg)
|
|
{
|
|
return static_cast<u16>(reg);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct cast_armv7_gpr<u32, false>
|
|
{
|
|
__forceinline static u32 to_gpr(const u32& value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
__forceinline static u32 from_gpr(const u32 reg)
|
|
{
|
|
return reg;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct cast_armv7_gpr<s8, false>
|
|
{
|
|
__forceinline static u32 to_gpr(const s8& value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
__forceinline static s8 from_gpr(const u32 reg)
|
|
{
|
|
return static_cast<s8>(reg);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct cast_armv7_gpr<s16, false>
|
|
{
|
|
__forceinline static u32 to_gpr(const s16& value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
__forceinline static s16 from_gpr(const u32 reg)
|
|
{
|
|
return static_cast<s16>(reg);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct cast_armv7_gpr<s32, false>
|
|
{
|
|
__forceinline static u32 to_gpr(const s32& value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
__forceinline static s32 from_gpr(const u32 reg)
|
|
{
|
|
return static_cast<s32>(reg);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct cast_armv7_gpr<bool, false>
|
|
{
|
|
__forceinline static u32 to_gpr(const bool& value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
__forceinline static bool from_gpr(const u32 reg)
|
|
{
|
|
return reinterpret_cast<const bool&>(reg);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
__forceinline u32 cast_to_armv7_gpr(const T& value)
|
|
{
|
|
return cast_armv7_gpr<T>::to_gpr(value);
|
|
}
|
|
|
|
template<typename T>
|
|
__forceinline T cast_from_armv7_gpr(const u32 reg)
|
|
{
|
|
return cast_armv7_gpr<T>::from_gpr(reg);
|
|
}
|