Skip to content

Commit

Permalink
Add CVT_NZCV_HFLAG instruction to IR
Browse files Browse the repository at this point in the history
  • Loading branch information
fleroviux committed Feb 9, 2025
1 parent 9d0dc61 commit 9edb901
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 24 deletions.
6 changes: 6 additions & 0 deletions src/dual/src/arm/dynarec/backend/arm64/arm64_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ void ARM64Backend::Execute(const ir::Function& function, bool debug) {
code.MOV(nzcv_reg, hflags_reg); // TODO(fleroviux): implement move elimination
break;
}
case ir::Instruction::Type::CVT_NZCV_HFLAG: {
const oaknut::WReg nzcv_reg = GetLocation(instruction->GetArg(0u).AsValue()).AsWReg();
const oaknut::WReg hflags_reg = GetLocation(instruction->GetOut(0u)).AsWReg();
code.MOV(hflags_reg, nzcv_reg); // TODO(fleroviux): implement move elimination
break;
}

// Control Flow
case ir::Instruction::Type::BR: {
Expand Down
46 changes: 23 additions & 23 deletions src/dual/src/arm/dynarec/dynarec_cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,33 +221,33 @@ void DynarecCPU::TestBackend() {
{
ir::Emitter emitter{*bb_loop, m_tmp_memory_arena};

const ir::U32Value& value_r0 = emitter.LDGPR(GPR::R0, Mode::User);

const ir::HostFlagsValue* hflags;
const ir::U32Value& result = emitter.ADD(value_r0, emitter.LDCONST(0xFFFFFFFFu), &hflags);
emitter.STGPR(GPR::R0, Mode::User, result);
emitter.STGPR(GPR::R8, Mode::User, emitter.LDGPR(GPR::R0, Mode::User));
emitter.STGPR(GPR::R0, Mode::User, emitter.LDGPR(GPR::R0, Mode::User));

emitter.STCPSR(emitter.LDCPSR());
emitter.STCPSR(emitter.LDCPSR());
emitter.STSPSR(Mode::IRQ, emitter.LDSPSR(Mode::IRQ));
emitter.STSPSR(Mode::FIQ, emitter.LDSPSR(Mode::FIQ));
emitter.STSPSR(Mode::IRQ, emitter.LDSPSR(Mode::IRQ));
emitter.STSPSR(Mode::FIQ, emitter.LDSPSR(Mode::FIQ));

emitter.BR_IF(ir::Condition::EQ, *hflags, *bb_exit, *bb_loop);
// const ir::U32Value& value_r0 = emitter.LDGPR(GPR::R0, Mode::User);
// const ir::HostFlagsValue* hflags;
// const ir::U32Value& result = emitter.ADD(value_r0, emitter.LDCONST(0xFFFFFFFFu), &hflags);
// emitter.STGPR(GPR::R0, Mode::User, result);
// emitter.STGPR(GPR::R8, Mode::User, emitter.LDGPR(GPR::R0, Mode::User));
// emitter.STGPR(GPR::R0, Mode::User, emitter.LDGPR(GPR::R0, Mode::User));
// emitter.STCPSR(emitter.LDCPSR());
// emitter.STCPSR(emitter.LDCPSR());
// emitter.STSPSR(Mode::IRQ, emitter.LDSPSR(Mode::IRQ));
// emitter.STSPSR(Mode::FIQ, emitter.LDSPSR(Mode::FIQ));
// emitter.STSPSR(Mode::IRQ, emitter.LDSPSR(Mode::IRQ));
// emitter.STSPSR(Mode::FIQ, emitter.LDSPSR(Mode::FIQ));
// emitter.BR_IF(ir::Condition::EQ, *hflags, *bb_exit, *bb_loop);

const ir::HostFlagsValue* add_hflags;
const ir::U32Value& add_result = emitter.ADD(emitter.LDGPR(GPR::R0, Mode::User), emitter.LDCONST(0xFFFFFFFFu), &add_hflags);
emitter.STGPR(GPR::R0, Mode::User, add_result);

const ir::U32Value& cpsr_old = emitter.LDCPSR();
const ir::U32Value& cpsr_new = emitter.ORR(emitter.BIC(cpsr_old, emitter.LDCONST(0xF0000000u)), emitter.CVT_HFLAG_NZCV(*add_hflags));
emitter.STCPSR(cpsr_new);

emitter.BR_IF(ir::Condition::EQ, emitter.CVT_NZCV_HFLAG(emitter.LDCPSR()), *bb_exit, *bb_loop);
}

{
ir::Emitter emitter{*bb_exit, m_tmp_memory_arena};

// const ir::HostFlagsValue* hflags;
// const ir::U32Value& r1_value = emitter.LDGPR(GPR::R1, Mode::User);
// const ir::U32Value& result_value = emitter.LSL(r1_value, emitter.LDCONST(1), &hflags);
// emitter.STGPR(GPR::R1, Mode::User, result_value);
// emitter.STCPSR(emitter.CVT_HFLAG_NZCV(*hflags));

emitter.EXIT();
}

Expand Down
1 change: 1 addition & 0 deletions src/dual/src/arm/dynarec/ir/disassemble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static const char* get_instruction_mnemonic(Instruction::Type type) {
case Instruction::Type::LDSPSR: return "ldspsr";
case Instruction::Type::STSPSR: return "stspsr";
case Instruction::Type::CVT_HFLAG_NZCV: return "cvt.hflag.nzcv";
case Instruction::Type::CVT_NZCV_HFLAG: return "cvt.nzcv.hflag";
case Instruction::Type::BR: return "br";
case Instruction::Type::BR_IF: return "br_if";
case Instruction::Type::EXIT: return "exit";
Expand Down
4 changes: 4 additions & 0 deletions src/dual/src/arm/dynarec/ir/emitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class Emitter {
return std::get<0>(Emit<U32Value>(Type::CVT_HFLAG_NZCV, 0u, hflag_value));
}

const HostFlagsValue& CVT_NZCV_HFLAG(const U32Value& nzcv_value) {
return std::get<0>(Emit<HostFlagsValue>(Type::CVT_NZCV_HFLAG, 0u, nzcv_value));
}

void BR(const BasicBlock& basic_block) {
Emit(Type::BR, 0u, basic_block);
}
Expand Down
2 changes: 1 addition & 1 deletion src/dual/src/arm/dynarec/ir/instruction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct Instruction {

// Flag Management
CVT_HFLAG_NZCV,
// ...
CVT_NZCV_HFLAG,

// Control Flow
BR,
Expand Down

0 comments on commit 9edb901

Please sign in to comment.