yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

arm_interface: Remove ARM11-isms from the CPU interface

This modifies the CPU interface to more accurately match an
AArch64-supporting CPU as opposed to an ARM11 one. Two of the methods
don't even make sense to keep around for this interface, as Adv Simd is
used, rather than the VFP in the primary execution state. This is
essentially a modernization change that should have occurred from the
get-go.
This commit is contained in:
Lioncash 2018-09-18 02:49:40 -04:00
parent a94b623dfb
commit b51e7e0288
7 changed files with 88 additions and 101 deletions

View File

@ -10,7 +10,7 @@
namespace Core { namespace Core {
/// Generic ARM11 CPU interface /// Generic ARMv8 CPU interface
class ARM_Interface : NonCopyable { class ARM_Interface : NonCopyable {
public: public:
virtual ~ARM_Interface() {} virtual ~ARM_Interface() {}
@ -19,9 +19,9 @@ public:
std::array<u64, 31> cpu_registers; std::array<u64, 31> cpu_registers;
u64 sp; u64 sp;
u64 pc; u64 pc;
u64 cpsr; u64 pstate;
std::array<u128, 32> fpu_registers; std::array<u128, 32> vector_registers;
u64 fpscr; u64 fpcr;
}; };
/// Runs the CPU until an event happens /// Runs the CPU until an event happens
@ -69,42 +69,50 @@ public:
*/ */
virtual void SetReg(int index, u64 value) = 0; virtual void SetReg(int index, u64 value) = 0;
virtual u128 GetExtReg(int index) const = 0; /**
* Gets the value of a specified vector register.
virtual void SetExtReg(int index, u128 value) = 0; *
* @param index The index of the vector register.
* @return the value within the vector register.
*/
virtual u128 GetVectorReg(int index) const = 0;
/** /**
* Gets the value of a VFP register * Sets a given value into a vector register.
* @param index Register index (0-31) *
* @return Returns the value in the register * @param index The index of the vector register.
* @param value The new value to place in the register.
*/ */
virtual u32 GetVFPReg(int index) const = 0; virtual void SetVectorReg(int index, u128 value) = 0;
/** /**
* Sets a VFP register to the given value * Get the current PSTATE register
* @param index Register index (0-31) * @return Returns the value of the PSTATE register
* @param value Value to set register to
*/ */
virtual void SetVFPReg(int index, u32 value) = 0; virtual u32 GetPSTATE() const = 0;
/** /**
* Get the current CPSR register * Set the current PSTATE register
* @return Returns the value of the CPSR register * @param pstate Value to set PSTATE to
*/ */
virtual u32 GetCPSR() const = 0; virtual void SetPSTATE(u32 pstate) = 0;
/**
* Set the current CPSR register
* @param cpsr Value to set CPSR to
*/
virtual void SetCPSR(u32 cpsr) = 0;
virtual VAddr GetTlsAddress() const = 0; virtual VAddr GetTlsAddress() const = 0;
virtual void SetTlsAddress(VAddr address) = 0; virtual void SetTlsAddress(VAddr address) = 0;
/**
* Gets the value within the TPIDR_EL0 (read/write software thread ID) register.
*
* @return the value within the register.
*/
virtual u64 GetTPIDR_EL0() const = 0; virtual u64 GetTPIDR_EL0() const = 0;
/**
* Sets a new value within the TPIDR_EL0 (read/write software thread ID) register.
*
* @param value The new value to place in the register.
*/
virtual void SetTPIDR_EL0(u64 value) = 0; virtual void SetTPIDR_EL0(u64 value) = 0;
/** /**
@ -119,6 +127,7 @@ public:
*/ */
virtual void LoadContext(const ThreadContext& ctx) = 0; virtual void LoadContext(const ThreadContext& ctx) = 0;
/// Clears the exclusive monitor's state.
virtual void ClearExclusiveState() = 0; virtual void ClearExclusiveState() = 0;
/// Prepare core for thread reschedule (if needed to correctly handle state) /// Prepare core for thread reschedule (if needed to correctly handle state)

View File

@ -194,29 +194,20 @@ void ARM_Dynarmic::SetReg(int index, u64 value) {
jit->SetRegister(index, value); jit->SetRegister(index, value);
} }
u128 ARM_Dynarmic::GetExtReg(int index) const { u128 ARM_Dynarmic::GetVectorReg(int index) const {
return jit->GetVector(index); return jit->GetVector(index);
} }
void ARM_Dynarmic::SetExtReg(int index, u128 value) { void ARM_Dynarmic::SetVectorReg(int index, u128 value) {
jit->SetVector(index, value); jit->SetVector(index, value);
} }
u32 ARM_Dynarmic::GetVFPReg(int /*index*/) const { u32 ARM_Dynarmic::GetPSTATE() const {
UNIMPLEMENTED();
return {};
}
void ARM_Dynarmic::SetVFPReg(int /*index*/, u32 /*value*/) {
UNIMPLEMENTED();
}
u32 ARM_Dynarmic::GetCPSR() const {
return jit->GetPstate(); return jit->GetPstate();
} }
void ARM_Dynarmic::SetCPSR(u32 cpsr) { void ARM_Dynarmic::SetPSTATE(u32 pstate) {
jit->SetPstate(cpsr); jit->SetPstate(pstate);
} }
u64 ARM_Dynarmic::GetTlsAddress() const { u64 ARM_Dynarmic::GetTlsAddress() const {
@ -239,18 +230,18 @@ void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
ctx.cpu_registers = jit->GetRegisters(); ctx.cpu_registers = jit->GetRegisters();
ctx.sp = jit->GetSP(); ctx.sp = jit->GetSP();
ctx.pc = jit->GetPC(); ctx.pc = jit->GetPC();
ctx.cpsr = jit->GetPstate(); ctx.pstate = jit->GetPstate();
ctx.fpu_registers = jit->GetVectors(); ctx.vector_registers = jit->GetVectors();
ctx.fpscr = jit->GetFpcr(); ctx.fpcr = jit->GetFpcr();
} }
void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) { void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
jit->SetRegisters(ctx.cpu_registers); jit->SetRegisters(ctx.cpu_registers);
jit->SetSP(ctx.sp); jit->SetSP(ctx.sp);
jit->SetPC(ctx.pc); jit->SetPC(ctx.pc);
jit->SetPstate(static_cast<u32>(ctx.cpsr)); jit->SetPstate(static_cast<u32>(ctx.pstate));
jit->SetVectors(ctx.fpu_registers); jit->SetVectors(ctx.vector_registers);
jit->SetFpcr(static_cast<u32>(ctx.fpscr)); jit->SetFpcr(static_cast<u32>(ctx.fpcr));
} }
void ARM_Dynarmic::PrepareReschedule() { void ARM_Dynarmic::PrepareReschedule() {

View File

@ -29,14 +29,12 @@ public:
u64 GetPC() const override; u64 GetPC() const override;
u64 GetReg(int index) const override; u64 GetReg(int index) const override;
void SetReg(int index, u64 value) override; void SetReg(int index, u64 value) override;
u128 GetExtReg(int index) const override; u128 GetVectorReg(int index) const override;
void SetExtReg(int index, u128 value) override; void SetVectorReg(int index, u128 value) override;
u32 GetVFPReg(int index) const override; u32 GetPSTATE() const override;
void SetVFPReg(int index, u32 value) override; void SetPSTATE(u32 pstate) override;
u32 GetCPSR() const override;
void Run() override; void Run() override;
void Step() override; void Step() override;
void SetCPSR(u32 cpsr) override;
VAddr GetTlsAddress() const override; VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override; void SetTlsAddress(VAddr address) override;
void SetTPIDR_EL0(u64 value) override; void SetTPIDR_EL0(u64 value) override;

View File

@ -131,33 +131,24 @@ void ARM_Unicorn::SetReg(int regn, u64 val) {
CHECKED(uc_reg_write(uc, treg, &val)); CHECKED(uc_reg_write(uc, treg, &val));
} }
u128 ARM_Unicorn::GetExtReg(int /*index*/) const { u128 ARM_Unicorn::GetVectorReg(int /*index*/) const {
UNIMPLEMENTED(); UNIMPLEMENTED();
static constexpr u128 res{}; static constexpr u128 res{};
return res; return res;
} }
void ARM_Unicorn::SetExtReg(int /*index*/, u128 /*value*/) { void ARM_Unicorn::SetVectorReg(int /*index*/, u128 /*value*/) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
u32 ARM_Unicorn::GetVFPReg(int /*index*/) const { u32 ARM_Unicorn::GetPSTATE() const {
UNIMPLEMENTED();
return {};
}
void ARM_Unicorn::SetVFPReg(int /*index*/, u32 /*value*/) {
UNIMPLEMENTED();
}
u32 ARM_Unicorn::GetCPSR() const {
u64 nzcv{}; u64 nzcv{};
CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &nzcv)); CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &nzcv));
return static_cast<u32>(nzcv); return static_cast<u32>(nzcv);
} }
void ARM_Unicorn::SetCPSR(u32 cpsr) { void ARM_Unicorn::SetPSTATE(u32 pstate) {
u64 nzcv = cpsr; u64 nzcv = pstate;
CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &nzcv)); CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &nzcv));
} }
@ -219,7 +210,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
CHECKED(uc_reg_read(uc, UC_ARM64_REG_SP, &ctx.sp)); CHECKED(uc_reg_read(uc, UC_ARM64_REG_SP, &ctx.sp));
CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &ctx.pc)); CHECKED(uc_reg_read(uc, UC_ARM64_REG_PC, &ctx.pc));
CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &ctx.cpsr)); CHECKED(uc_reg_read(uc, UC_ARM64_REG_NZCV, &ctx.pstate));
for (auto i = 0; i < 29; ++i) { for (auto i = 0; i < 29; ++i) {
uregs[i] = UC_ARM64_REG_X0 + i; uregs[i] = UC_ARM64_REG_X0 + i;
@ -234,7 +225,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
for (int i = 0; i < 32; ++i) { for (int i = 0; i < 32; ++i) {
uregs[i] = UC_ARM64_REG_Q0 + i; uregs[i] = UC_ARM64_REG_Q0 + i;
tregs[i] = &ctx.fpu_registers[i]; tregs[i] = &ctx.vector_registers[i];
} }
CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32)); CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));
@ -246,7 +237,7 @@ void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
CHECKED(uc_reg_write(uc, UC_ARM64_REG_SP, &ctx.sp)); CHECKED(uc_reg_write(uc, UC_ARM64_REG_SP, &ctx.sp));
CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &ctx.pc)); CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &ctx.pc));
CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &ctx.cpsr)); CHECKED(uc_reg_write(uc, UC_ARM64_REG_NZCV, &ctx.pstate));
for (int i = 0; i < 29; ++i) { for (int i = 0; i < 29; ++i) {
uregs[i] = UC_ARM64_REG_X0 + i; uregs[i] = UC_ARM64_REG_X0 + i;
@ -261,7 +252,7 @@ void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
for (auto i = 0; i < 32; ++i) { for (auto i = 0; i < 32; ++i) {
uregs[i] = UC_ARM64_REG_Q0 + i; uregs[i] = UC_ARM64_REG_Q0 + i;
tregs[i] = (void*)&ctx.fpu_registers[i]; tregs[i] = (void*)&ctx.vector_registers[i];
} }
CHECKED(uc_reg_write_batch(uc, uregs, tregs, 32)); CHECKED(uc_reg_write_batch(uc, uregs, tregs, 32));

View File

@ -22,12 +22,10 @@ public:
u64 GetPC() const override; u64 GetPC() const override;
u64 GetReg(int index) const override; u64 GetReg(int index) const override;
void SetReg(int index, u64 value) override; void SetReg(int index, u64 value) override;
u128 GetExtReg(int index) const override; u128 GetVectorReg(int index) const override;
void SetExtReg(int index, u128 value) override; void SetVectorReg(int index, u128 value) override;
u32 GetVFPReg(int index) const override; u32 GetPSTATE() const override;
void SetVFPReg(int index, u32 value) override; void SetPSTATE(u32 pstate) override;
u32 GetCPSR() const override;
void SetCPSR(u32 cpsr) override;
VAddr GetTlsAddress() const override; VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override; void SetTlsAddress(VAddr address) override;
void SetTPIDR_EL0(u64 value) override; void SetTPIDR_EL0(u64 value) override;

View File

@ -65,9 +65,9 @@ constexpr u32 MSG_WAITALL = 8;
constexpr u32 LR_REGISTER = 30; constexpr u32 LR_REGISTER = 30;
constexpr u32 SP_REGISTER = 31; constexpr u32 SP_REGISTER = 31;
constexpr u32 PC_REGISTER = 32; constexpr u32 PC_REGISTER = 32;
constexpr u32 CPSR_REGISTER = 33; constexpr u32 PSTATE_REGISTER = 33;
constexpr u32 UC_ARM64_REG_Q0 = 34; constexpr u32 UC_ARM64_REG_Q0 = 34;
constexpr u32 FPSCR_REGISTER = 66; constexpr u32 FPCR_REGISTER = 66;
// TODO/WiP - Used while working on support for FPU // TODO/WiP - Used while working on support for FPU
constexpr u32 TODO_DUMMY_REG_997 = 997; constexpr u32 TODO_DUMMY_REG_997 = 997;
@ -116,7 +116,7 @@ constexpr char target_xml[] =
<reg name="pc" bitsize="64" type="code_ptr"/> <reg name="pc" bitsize="64" type="code_ptr"/>
<flags id="cpsr_flags" size="4"> <flags id="pstate_flags" size="4">
<field name="SP" start="0" end="0"/> <field name="SP" start="0" end="0"/>
<field name="" start="1" end="1"/> <field name="" start="1" end="1"/>
<field name="EL" start="2" end="3"/> <field name="EL" start="2" end="3"/>
@ -135,7 +135,7 @@ constexpr char target_xml[] =
<field name="Z" start="30" end="30"/> <field name="Z" start="30" end="30"/>
<field name="N" start="31" end="31"/> <field name="N" start="31" end="31"/>
</flags> </flags>
<reg name="cpsr" bitsize="32" type="cpsr_flags"/> <reg name="pstate" bitsize="32" type="pstate_flags"/>
</feature> </feature>
<feature name="org.gnu.gdb.aarch64.fpu"> <feature name="org.gnu.gdb.aarch64.fpu">
</feature> </feature>
@ -227,10 +227,10 @@ static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) {
return thread->context.sp; return thread->context.sp;
} else if (id == PC_REGISTER) { } else if (id == PC_REGISTER) {
return thread->context.pc; return thread->context.pc;
} else if (id == CPSR_REGISTER) { } else if (id == PSTATE_REGISTER) {
return thread->context.cpsr; return thread->context.pstate;
} else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { } else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) {
return thread->context.fpu_registers[id - UC_ARM64_REG_Q0][0]; return thread->context.vector_registers[id - UC_ARM64_REG_Q0][0];
} else { } else {
return 0; return 0;
} }
@ -247,10 +247,10 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
thread->context.sp = val; thread->context.sp = val;
} else if (id == PC_REGISTER) { } else if (id == PC_REGISTER) {
thread->context.pc = val; thread->context.pc = val;
} else if (id == CPSR_REGISTER) { } else if (id == PSTATE_REGISTER) {
thread->context.cpsr = val; thread->context.pstate = val;
} else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { } else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) {
thread->context.fpu_registers[id - (CPSR_REGISTER + 1)][0] = val; thread->context.vector_registers[id - (PSTATE_REGISTER + 1)][0] = val;
} }
} }
@ -781,11 +781,11 @@ static void ReadRegister() {
LongToGdbHex(reply, RegRead(id, current_thread)); LongToGdbHex(reply, RegRead(id, current_thread));
} else if (id == PC_REGISTER) { } else if (id == PC_REGISTER) {
LongToGdbHex(reply, RegRead(id, current_thread)); LongToGdbHex(reply, RegRead(id, current_thread));
} else if (id == CPSR_REGISTER) { } else if (id == PSTATE_REGISTER) {
IntToGdbHex(reply, (u32)RegRead(id, current_thread)); IntToGdbHex(reply, static_cast<u32>(RegRead(id, current_thread)));
} else if (id >= UC_ARM64_REG_Q0 && id < FPSCR_REGISTER) { } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
LongToGdbHex(reply, RegRead(id, current_thread)); LongToGdbHex(reply, RegRead(id, current_thread));
} else if (id == FPSCR_REGISTER) { } else if (id == FPCR_REGISTER) {
LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_998, current_thread)); LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_998, current_thread));
} else { } else {
LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_997, current_thread)); LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_997, current_thread));
@ -811,7 +811,7 @@ static void ReadRegisters() {
bufptr += 16; bufptr += 16;
IntToGdbHex(bufptr, (u32)RegRead(CPSR_REGISTER, current_thread)); IntToGdbHex(bufptr, static_cast<u32>(RegRead(PSTATE_REGISTER, current_thread)));
bufptr += 8; bufptr += 8;
@ -843,11 +843,11 @@ static void WriteRegister() {
RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
} else if (id == PC_REGISTER) { } else if (id == PC_REGISTER) {
RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
} else if (id == CPSR_REGISTER) { } else if (id == PSTATE_REGISTER) {
RegWrite(id, GdbHexToInt(buffer_ptr), current_thread); RegWrite(id, GdbHexToInt(buffer_ptr), current_thread);
} else if (id >= UC_ARM64_REG_Q0 && id < FPSCR_REGISTER) { } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
} else if (id == FPSCR_REGISTER) { } else if (id == FPCR_REGISTER) {
RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr), current_thread); RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr), current_thread);
} else { } else {
RegWrite(TODO_DUMMY_REG_997, GdbHexToLong(buffer_ptr), current_thread); RegWrite(TODO_DUMMY_REG_997, GdbHexToLong(buffer_ptr), current_thread);
@ -866,16 +866,16 @@ static void WriteRegisters() {
if (command_buffer[0] != 'G') if (command_buffer[0] != 'G')
return SendReply("E01"); return SendReply("E01");
for (u32 i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) { for (u32 i = 0, reg = 0; reg <= FPCR_REGISTER; i++, reg++) {
if (reg <= SP_REGISTER) { if (reg <= SP_REGISTER) {
RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else if (reg == PC_REGISTER) { } else if (reg == PC_REGISTER) {
RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else if (reg == CPSR_REGISTER) { } else if (reg == PSTATE_REGISTER) {
RegWrite(CPSR_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread); RegWrite(PSTATE_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread);
} else if (reg >= UC_ARM64_REG_Q0 && reg < FPSCR_REGISTER) { } else if (reg >= UC_ARM64_REG_Q0 && reg < FPCR_REGISTER) {
RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else if (reg == FPSCR_REGISTER) { } else if (reg == FPCR_REGISTER) {
RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr + i * 16), current_thread); RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else { } else {
UNIMPLEMENTED(); UNIMPLEMENTED();

View File

@ -217,8 +217,8 @@ static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAdd
context.cpu_registers[0] = arg; context.cpu_registers[0] = arg;
context.pc = entry_point; context.pc = entry_point;
context.sp = stack_top; context.sp = stack_top;
context.cpsr = 0; context.pstate = 0;
context.fpscr = 0; context.fpcr = 0;
} }
ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point, ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point,