A64: PSTATE access and tests
This commit is contained in:
parent
23f3afe0b3
commit
e8bcf72ee5
6 changed files with 86 additions and 2 deletions
|
@ -83,6 +83,11 @@ public:
|
||||||
/// Modify FPCR.
|
/// Modify FPCR.
|
||||||
void SetFpcr(std::uint32_t value);
|
void SetFpcr(std::uint32_t value);
|
||||||
|
|
||||||
|
/// View PSTATE
|
||||||
|
std::uint32_t GetPstate() const;
|
||||||
|
/// Modify PSTATE
|
||||||
|
void SetPstate(std::uint32_t value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if Jit::Run was called but hasn't returned yet.
|
* Returns true if Jit::Run was called but hasn't returned yet.
|
||||||
* i.e.: We're in a callback.
|
* i.e.: We're in a callback.
|
||||||
|
|
|
@ -128,7 +128,8 @@ void A64EmitX64::EmitA64SetNZCV(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt32();
|
Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt32();
|
||||||
code->and_(to_store, 0b11000001'00000001);
|
code->and_(to_store, 0b11000001'00000001);
|
||||||
code->imul(to_store, to_store, 0b00010000'00100001);
|
code->imul(to_store, to_store, 0b00010000'00100001);
|
||||||
code->and_(to_store, 0xFF000000);
|
code->shl(to_store, 16);
|
||||||
|
code->and_(to_store, 0xF0000000);
|
||||||
code->mov(dword[r15 + offsetof(A64JitState, CPSR_nzcv)], to_store);
|
code->mov(dword[r15 + offsetof(A64JitState, CPSR_nzcv)], to_store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,14 @@ public:
|
||||||
jit_state.SetFpcr(value);
|
jit_state.SetFpcr(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GetPstate() const {
|
||||||
|
return jit_state.GetPstate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPstate(u32 value) {
|
||||||
|
jit_state.SetPstate(value);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsExecuting() const {
|
bool IsExecuting() const {
|
||||||
return is_executing;
|
return is_executing;
|
||||||
}
|
}
|
||||||
|
@ -257,6 +265,14 @@ void Jit::SetFpcr(u32 value) {
|
||||||
impl->SetFpcr(value);
|
impl->SetFpcr(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 Jit::GetPstate() const {
|
||||||
|
return impl->GetPstate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit::SetPstate(u32 value) {
|
||||||
|
impl->SetPstate(value);
|
||||||
|
}
|
||||||
|
|
||||||
bool Jit::IsExecuting() const {
|
bool Jit::IsExecuting() const {
|
||||||
return impl->IsExecuting();
|
return impl->IsExecuting();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,12 @@ struct A64JitState {
|
||||||
|
|
||||||
u32 CPSR_nzcv = 0;
|
u32 CPSR_nzcv = 0;
|
||||||
u32 FPSCR_nzcv = 0;
|
u32 FPSCR_nzcv = 0;
|
||||||
|
u32 GetPstate() const {
|
||||||
|
return CPSR_nzcv;
|
||||||
|
}
|
||||||
|
void SetPstate(u32 new_pstate) {
|
||||||
|
CPSR_nzcv = new_pstate & 0xF0000000;
|
||||||
|
}
|
||||||
|
|
||||||
alignas(16) std::array<u64, 64> vec{}; // Extension registers.
|
alignas(16) std::array<u64, 64> vec{}; // Extension registers.
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,7 @@ bool Inst::WritesToCPSR() const {
|
||||||
case Opcode::A32OrQFlag:
|
case Opcode::A32OrQFlag:
|
||||||
case Opcode::A32SetGEFlags:
|
case Opcode::A32SetGEFlags:
|
||||||
case Opcode::A32SetGEFlagsCompressed:
|
case Opcode::A32SetGEFlagsCompressed:
|
||||||
|
case Opcode::A64SetNZCV:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -387,7 +388,7 @@ void Inst::Use(const Value& value) {
|
||||||
break;
|
break;
|
||||||
case Opcode::GetNZCVFromOp:
|
case Opcode::GetNZCVFromOp:
|
||||||
ASSERT_MSG(!value.GetInst()->nzcv_inst, "Only one of each type of pseudo-op allowed");
|
ASSERT_MSG(!value.GetInst()->nzcv_inst, "Only one of each type of pseudo-op allowed");
|
||||||
ASSERT_MSG(MayGetNZCVFromOp(), "This instruction doesn't support the GetNZCVFromOp pseduo-op");
|
ASSERT_MSG(value.GetInst()->MayGetNZCVFromOp(), "This value doesn't support the GetNZCVFromOp pseduo-op");
|
||||||
value.GetInst()->nzcv_inst = this;
|
value.GetInst()->nzcv_inst = this;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -113,3 +113,58 @@ TEST_CASE("A64: Bitmasks", "[a64]") {
|
||||||
REQUIRE(jit.GetRegister(2) == 1);
|
REQUIRE(jit.GetRegister(2) == 1);
|
||||||
REQUIRE(jit.GetPC() == 12);
|
REQUIRE(jit.GetPC() == 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A64: ANDS NZCV", "[a64]") {
|
||||||
|
TestEnv env;
|
||||||
|
Dynarmic::A64::Jit jit{Dynarmic::A64::UserConfig{&env}};
|
||||||
|
|
||||||
|
env.code_mem[0] = 0x6a020020; // ANDS W0, W1, W2
|
||||||
|
env.code_mem[1] = 0x14000000; // B .
|
||||||
|
|
||||||
|
SECTION("N=1, Z=0") {
|
||||||
|
jit.SetRegister(0, 0);
|
||||||
|
jit.SetRegister(1, 0xFFFFFFFF);
|
||||||
|
jit.SetRegister(2, 0xFFFFFFFF);
|
||||||
|
jit.SetPC(0);
|
||||||
|
|
||||||
|
env.ticks_left = 2;
|
||||||
|
jit.Run();
|
||||||
|
|
||||||
|
REQUIRE(jit.GetRegister(0) == 0xFFFFFFFF);
|
||||||
|
REQUIRE(jit.GetRegister(1) == 0xFFFFFFFF);
|
||||||
|
REQUIRE(jit.GetRegister(2) == 0xFFFFFFFF);
|
||||||
|
REQUIRE(jit.GetPC() == 4);
|
||||||
|
REQUIRE((jit.GetPstate() & 0xF0000000) == 0x80000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("N=0, Z=1") {
|
||||||
|
jit.SetRegister(0, 0);
|
||||||
|
jit.SetRegister(1, 0xFFFFFFFF);
|
||||||
|
jit.SetRegister(2, 0x00000000);
|
||||||
|
jit.SetPC(0);
|
||||||
|
|
||||||
|
env.ticks_left = 2;
|
||||||
|
jit.Run();
|
||||||
|
|
||||||
|
REQUIRE(jit.GetRegister(0) == 0x00000000);
|
||||||
|
REQUIRE(jit.GetRegister(1) == 0xFFFFFFFF);
|
||||||
|
REQUIRE(jit.GetRegister(2) == 0x00000000);
|
||||||
|
REQUIRE(jit.GetPC() == 4);
|
||||||
|
REQUIRE((jit.GetPstate() & 0xF0000000) == 0x40000000);
|
||||||
|
}
|
||||||
|
SECTION("N=0, Z=0") {
|
||||||
|
jit.SetRegister(0, 0);
|
||||||
|
jit.SetRegister(1, 0x12345678);
|
||||||
|
jit.SetRegister(2, 0x7324a993);
|
||||||
|
jit.SetPC(0);
|
||||||
|
|
||||||
|
env.ticks_left = 2;
|
||||||
|
jit.Run();
|
||||||
|
|
||||||
|
REQUIRE(jit.GetRegister(0) == 0x12240010);
|
||||||
|
REQUIRE(jit.GetRegister(1) == 0x12345678);
|
||||||
|
REQUIRE(jit.GetRegister(2) == 0x7324a993);
|
||||||
|
REQUIRE(jit.GetPC() == 4);
|
||||||
|
REQUIRE((jit.GetPstate() & 0xF0000000) == 0x00000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue