From b1f0cf9278ab22c3c191f69204f8557c40f18c98 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Mon, 1 Jan 2018 15:47:56 +0000 Subject: [PATCH] A32: Split off A32 specific IREmitter --- src/CMakeLists.txt | 2 + src/backend_x64/emit_x64.cpp | 6 +- src/frontend/A32/ir_emitter.cpp | 328 +++++++++++ src/frontend/A32/ir_emitter.h | 92 +++ src/frontend/A32/location_descriptor.h | 8 +- src/frontend/A32/translate/translate_arm.cpp | 8 +- .../A32/translate/translate_arm/extension.cpp | 2 +- .../translate/translate_arm/load_store.cpp | 6 +- .../A32/translate/translate_arm/saturated.cpp | 4 +- .../translate/translate_arm/translate_arm.h | 10 +- .../A32/translate/translate_thumb.cpp | 6 +- src/frontend/ir/ir_emitter.cpp | 535 ++++-------------- src/frontend/ir/ir_emitter.h | 65 +-- src/frontend/ir/location_descriptor.cpp | 2 +- src/frontend/ir/location_descriptor.h | 11 +- 15 files changed, 571 insertions(+), 514 deletions(-) create mode 100644 src/frontend/A32/ir_emitter.cpp create mode 100644 src/frontend/A32/ir_emitter.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7486fe62..c09f63f9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,8 @@ add_library(dynarmic frontend/A32/disassembler/disassembler_arm.cpp frontend/A32/disassembler/disassembler_thumb.cpp frontend/A32/FPSCR.h + frontend/A32/ir_emitter.cpp + frontend/A32/ir_emitter.h frontend/A32/location_descriptor.cpp frontend/A32/location_descriptor.h frontend/A32/PSR.h diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 3d2be2d5..a62ce569 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -3464,7 +3464,7 @@ void A32EmitX64::EmitTerminal(IR::Term::LinkBlock terminal, A32::LocationDescrip code->cmp(qword[r15 + offsetof(JitState, cycles_remaining)], 0); - patch_information[terminal.next.value].jg.emplace_back(code->getCurr()); + patch_information[terminal.next.Value()].jg.emplace_back(code->getCurr()); if (auto next_bb = GetBasicBlock(terminal.next)) { EmitPatchJg(terminal.next, next_bb->entrypoint); } else { @@ -3477,7 +3477,7 @@ void A32EmitX64::EmitTerminal(IR::Term::LinkBlock terminal, A32::LocationDescrip code->align(16); code->L(dest); code->mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC()); - PushRSBHelper(rax, rbx, terminal.next.value); + PushRSBHelper(rax, rbx, terminal.next.Value()); code->ForceReturnFromRunCode(); code->SwitchToNearCode(); } @@ -3487,7 +3487,7 @@ void A32EmitX64::EmitTerminal(IR::Term::LinkBlockFast terminal, A32::LocationDes code->mov(dword[r15 + offsetof(JitState, CPSR_et)], CalculateCpsr_et(terminal.next)); } - patch_information[terminal.next.value].jmp.emplace_back(code->getCurr()); + patch_information[terminal.next.Value()].jmp.emplace_back(code->getCurr()); if (auto next_bb = GetBasicBlock(terminal.next)) { EmitPatchJmp(terminal.next, next_bb->entrypoint); } else { diff --git a/src/frontend/A32/ir_emitter.cpp b/src/frontend/A32/ir_emitter.cpp new file mode 100644 index 00000000..8cfd2e50 --- /dev/null +++ b/src/frontend/A32/ir_emitter.cpp @@ -0,0 +1,328 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "common/assert.h" +#include "frontend/A32/ir_emitter.h" +#include "frontend/ir/opcodes.h" + +namespace Dynarmic { +namespace A32 { + +using Opcode = IR::Opcode; + +u32 IREmitter::PC() { + u32 offset = current_location.TFlag() ? 4 : 8; + return current_location.PC() + offset; +} + +u32 IREmitter::AlignPC(size_t alignment) { + u32 pc = PC(); + return static_cast(pc - pc % alignment); +} + +IR::Value IREmitter::GetRegister(A32::Reg reg) { + if (reg == A32::Reg::PC) { + return Imm32(PC()); + } + return Inst(Opcode::GetRegister, { IR::Value(reg) }); +} + +IR::Value IREmitter::GetExtendedRegister(A32::ExtReg reg) { + if (A32::IsSingleExtReg(reg)) { + return Inst(Opcode::GetExtendedRegister32, {IR::Value(reg)}); + } + + if (A32::IsDoubleExtReg(reg)) { + return Inst(Opcode::GetExtendedRegister64, {IR::Value(reg)}); + } + + ASSERT_MSG(false, "Invalid reg."); +} + +void IREmitter::SetRegister(const A32::Reg reg, const IR::Value& value) { + ASSERT(reg != A32::Reg::PC); + Inst(Opcode::SetRegister, { IR::Value(reg), value }); +} + +void IREmitter::SetExtendedRegister(const A32::ExtReg reg, const IR::Value& value) { + if (A32::IsSingleExtReg(reg)) { + Inst(Opcode::SetExtendedRegister32, {IR::Value(reg), value}); + } else if (A32::IsDoubleExtReg(reg)) { + Inst(Opcode::SetExtendedRegister64, {IR::Value(reg), value}); + } else { + ASSERT_MSG(false, "Invalid reg."); + } +} + +void IREmitter::ALUWritePC(const IR::Value& value) { + // This behaviour is ARM version-dependent. + // The below implementation is for ARMv6k + BranchWritePC(value); +} + +void IREmitter::BranchWritePC(const IR::Value& value) { + if (!current_location.TFlag()) { + auto new_pc = And(value, Imm32(0xFFFFFFFC)); + Inst(Opcode::SetRegister, { IR::Value(A32::Reg::PC), new_pc }); + } else { + auto new_pc = And(value, Imm32(0xFFFFFFFE)); + Inst(Opcode::SetRegister, { IR::Value(A32::Reg::PC), new_pc }); + } +} + +void IREmitter::BXWritePC(const IR::Value& value) { + Inst(Opcode::BXWritePC, {value}); +} + +void IREmitter::LoadWritePC(const IR::Value& value) { + // This behaviour is ARM version-dependent. + // The below implementation is for ARMv6k + BXWritePC(value); +} + +void IREmitter::CallSupervisor(const IR::Value& value) { + Inst(Opcode::CallSupervisor, {value}); +} + +void IREmitter::PushRSB(const A32::LocationDescriptor& return_location) { + Inst(Opcode::PushRSB, {IR::Value(return_location.UniqueHash())}); +} + +IR::Value IREmitter::GetCpsr() { + return Inst(Opcode::GetCpsr, {}); +} + +void IREmitter::SetCpsr(const IR::Value& value) { + Inst(Opcode::SetCpsr, {value}); +} + +void IREmitter::SetCpsrNZCV(const IR::Value& value) { + Inst(Opcode::SetCpsrNZCV, {value}); +} + +void IREmitter::SetCpsrNZCVQ(const IR::Value& value) { + Inst(Opcode::SetCpsrNZCVQ, {value}); +} + +IR::Value IREmitter::GetCFlag() { + return Inst(Opcode::GetCFlag, {}); +} + +void IREmitter::SetNFlag(const IR::Value& value) { + Inst(Opcode::SetNFlag, {value}); +} + +void IREmitter::SetZFlag(const IR::Value& value) { + Inst(Opcode::SetZFlag, {value}); +} + +void IREmitter::SetCFlag(const IR::Value& value) { + Inst(Opcode::SetCFlag, {value}); +} + +void IREmitter::SetVFlag(const IR::Value& value) { + Inst(Opcode::SetVFlag, {value}); +} + +void IREmitter::OrQFlag(const IR::Value& value) { + Inst(Opcode::OrQFlag, {value}); +} + +IR::Value IREmitter::GetGEFlags() { + return Inst(Opcode::GetGEFlags, {}); +} + +void IREmitter::SetGEFlags(const IR::Value& value) { + Inst(Opcode::SetGEFlags, {value}); +} + +void IREmitter::SetGEFlagsCompressed(const IR::Value& value) { + Inst(Opcode::SetGEFlagsCompressed, {value}); +} + +IR::Value IREmitter::GetFpscr() { + return Inst(Opcode::GetFpscr, {}); +} + +void IREmitter::SetFpscr(const IR::Value& new_fpscr) { + Inst(Opcode::SetFpscr, {new_fpscr}); +} + +IR::Value IREmitter::GetFpscrNZCV() { + return Inst(Opcode::GetFpscrNZCV, {}); +} + +void IREmitter::SetFpscrNZCV(const IR::Value& new_fpscr_nzcv) { + Inst(Opcode::SetFpscrNZCV, {new_fpscr_nzcv}); +} + +void IREmitter::ClearExclusive() { + Inst(Opcode::ClearExclusive, {}); +} + +void IREmitter::SetExclusive(const IR::Value& vaddr, size_t byte_size) { + ASSERT(byte_size == 1 || byte_size == 2 || byte_size == 4 || byte_size == 8 || byte_size == 16); + Inst(Opcode::SetExclusive, {vaddr, Imm8(u8(byte_size))}); +} + +IR::Value IREmitter::ReadMemory8(const IR::Value& vaddr) { + return Inst(Opcode::ReadMemory8, {vaddr}); +} + +IR::Value IREmitter::ReadMemory16(const IR::Value& vaddr) { + auto value = Inst(Opcode::ReadMemory16, {vaddr}); + return current_location.EFlag() ? ByteReverseHalf(value) : value; +} + +IR::Value IREmitter::ReadMemory32(const IR::Value& vaddr) { + auto value = Inst(Opcode::ReadMemory32, {vaddr}); + return current_location.EFlag() ? ByteReverseWord(value) : value; +} + +IR::Value IREmitter::ReadMemory64(const IR::Value& vaddr) { + auto value = Inst(Opcode::ReadMemory64, {vaddr}); + return current_location.EFlag() ? ByteReverseDual(value) : value; +} + +void IREmitter::WriteMemory8(const IR::Value& vaddr, const IR::Value& value) { + Inst(Opcode::WriteMemory8, {vaddr, value}); +} + +void IREmitter::WriteMemory16(const IR::Value& vaddr, const IR::Value& value) { + if (current_location.EFlag()) { + auto v = ByteReverseHalf(value); + Inst(Opcode::WriteMemory16, {vaddr, v}); + } else { + Inst(Opcode::WriteMemory16, {vaddr, value}); + } +} + +void IREmitter::WriteMemory32(const IR::Value& vaddr, const IR::Value& value) { + if (current_location.EFlag()) { + auto v = ByteReverseWord(value); + Inst(Opcode::WriteMemory32, {vaddr, v}); + } else { + Inst(Opcode::WriteMemory32, {vaddr, value}); + } +} + +void IREmitter::WriteMemory64(const IR::Value& vaddr, const IR::Value& value) { + if (current_location.EFlag()) { + auto v = ByteReverseDual(value); + Inst(Opcode::WriteMemory64, {vaddr, v}); + } else { + Inst(Opcode::WriteMemory64, {vaddr, value}); + } +} + +IR::Value IREmitter::ExclusiveWriteMemory8(const IR::Value& vaddr, const IR::Value& value) { + return Inst(Opcode::ExclusiveWriteMemory8, {vaddr, value}); +} + +IR::Value IREmitter::ExclusiveWriteMemory16(const IR::Value& vaddr, const IR::Value& value) { + if (current_location.EFlag()) { + auto v = ByteReverseHalf(value); + return Inst(Opcode::ExclusiveWriteMemory16, {vaddr, v}); + } else { + return Inst(Opcode::ExclusiveWriteMemory16, {vaddr, value}); + } +} + +IR::Value IREmitter::ExclusiveWriteMemory32(const IR::Value& vaddr, const IR::Value& value) { + if (current_location.EFlag()) { + auto v = ByteReverseWord(value); + return Inst(Opcode::ExclusiveWriteMemory32, {vaddr, v}); + } else { + return Inst(Opcode::ExclusiveWriteMemory32, {vaddr, value}); + } +} + +IR::Value IREmitter::ExclusiveWriteMemory64(const IR::Value& vaddr, const IR::Value& value_lo, const IR::Value& value_hi) { + if (current_location.EFlag()) { + auto vlo = ByteReverseWord(value_lo); + auto vhi = ByteReverseWord(value_hi); + return Inst(Opcode::ExclusiveWriteMemory64, {vaddr, vlo, vhi}); + } else { + return Inst(Opcode::ExclusiveWriteMemory64, {vaddr, value_lo, value_hi}); + } +} + +void IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRd, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2) { + ASSERT(coproc_no <= 15); + std::array coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc1), + static_cast(CRd), + static_cast(CRn), + static_cast(CRm), + static_cast(opc2)}; + Inst(Opcode::CoprocInternalOperation, {IR::Value(coproc_info)}); +} + +void IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2, const IR::Value& word) { + ASSERT(coproc_no <= 15); + std::array coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc1), + static_cast(CRn), + static_cast(CRm), + static_cast(opc2)}; + Inst(Opcode::CoprocSendOneWord, {IR::Value(coproc_info), word}); +} + +void IREmitter::CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm, const IR::Value& word1, const IR::Value& word2) { + ASSERT(coproc_no <= 15); + std::array coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc), + static_cast(CRm)}; + Inst(Opcode::CoprocSendTwoWords, {IR::Value(coproc_info), word1, word2}); +} + +IR::Value IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2) { + ASSERT(coproc_no <= 15); + std::array coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc1), + static_cast(CRn), + static_cast(CRm), + static_cast(opc2)}; + return Inst(Opcode::CoprocGetOneWord, {IR::Value(coproc_info)}); +} + +IR::Value IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm) { + ASSERT(coproc_no <= 15); + std::array coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc), + static_cast(CRm)}; + return Inst(Opcode::CoprocGetTwoWords, {IR::Value(coproc_info)}); +} + +void IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const IR::Value& address, bool has_option, u8 option) { + ASSERT(coproc_no <= 15); + std::array coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(long_transfer ? 1 : 0), + static_cast(CRd), + static_cast(has_option ? 1 : 0), + static_cast(option)}; + Inst(Opcode::CoprocLoadWords, {IR::Value(coproc_info), address}); +} + +void IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const IR::Value& address, bool has_option, u8 option) { + ASSERT(coproc_no <= 15); + std::array coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(long_transfer ? 1 : 0), + static_cast(CRd), + static_cast(has_option ? 1 : 0), + static_cast(option)}; + Inst(Opcode::CoprocStoreWords, {IR::Value(coproc_info), address}); +} + +} // namespace IR +} // namespace Dynarmic diff --git a/src/frontend/A32/ir_emitter.h b/src/frontend/A32/ir_emitter.h new file mode 100644 index 00000000..f6cf1393 --- /dev/null +++ b/src/frontend/A32/ir_emitter.h @@ -0,0 +1,92 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#pragma once + +#include + +#include + +#include "common/common_types.h" +#include "frontend/A32/location_descriptor.h" +#include "frontend/A32/types.h" +#include "frontend/ir/ir_emitter.h" +#include "frontend/ir/value.h" + +namespace Dynarmic { +namespace A32 { + +/** + * Convenience class to construct a basic block of the intermediate representation. + * `block` is the resulting block. + * The user of this class updates `current_location` as appropriate. + */ +class IREmitter : public IR::IREmitter { +public: + explicit IREmitter(A32::LocationDescriptor descriptor) : IR::IREmitter(descriptor), current_location(descriptor) {} + + A32::LocationDescriptor current_location; + + u32 PC(); + u32 AlignPC(size_t alignment); + + IR::Value GetRegister(A32::Reg source_reg); + IR::Value GetExtendedRegister(A32::ExtReg source_reg); + void SetRegister(const A32::Reg dest_reg, const IR::Value& value); + void SetExtendedRegister(const A32::ExtReg dest_reg, const IR::Value& value); + + void ALUWritePC(const IR::Value& value); + void BranchWritePC(const IR::Value& value); + void BXWritePC(const IR::Value& value); + void LoadWritePC(const IR::Value& value); + void CallSupervisor(const IR::Value& value); + void PushRSB(const A32::LocationDescriptor& return_location); + + IR::Value GetCpsr(); + void SetCpsr(const IR::Value& value); + void SetCpsrNZCV(const IR::Value& value); + void SetCpsrNZCVQ(const IR::Value& value); + IR::Value GetCFlag(); + void SetNFlag(const IR::Value& value); + void SetZFlag(const IR::Value& value); + void SetCFlag(const IR::Value& value); + void SetVFlag(const IR::Value& value); + void OrQFlag(const IR::Value& value); + IR::Value GetGEFlags(); + void SetGEFlags(const IR::Value& value); + void SetGEFlagsCompressed(const IR::Value& value); + + IR::Value GetFpscr(); + void SetFpscr(const IR::Value& new_fpscr); + IR::Value GetFpscrNZCV(); + void SetFpscrNZCV(const IR::Value& new_fpscr_nzcv); + + void ClearExclusive(); + void SetExclusive(const IR::Value& vaddr, size_t byte_size); + IR::Value ReadMemory8(const IR::Value& vaddr); + IR::Value ReadMemory16(const IR::Value& vaddr); + IR::Value ReadMemory32(const IR::Value& vaddr); + IR::Value ReadMemory64(const IR::Value& vaddr); + void WriteMemory8(const IR::Value& vaddr, const IR::Value& value); + void WriteMemory16(const IR::Value& vaddr, const IR::Value& value); + void WriteMemory32(const IR::Value& vaddr, const IR::Value& value); + void WriteMemory64(const IR::Value& vaddr, const IR::Value& value); + IR::Value ExclusiveWriteMemory8(const IR::Value& vaddr, const IR::Value& value); + IR::Value ExclusiveWriteMemory16(const IR::Value& vaddr, const IR::Value& value); + IR::Value ExclusiveWriteMemory32(const IR::Value& vaddr, const IR::Value& value); + IR::Value ExclusiveWriteMemory64(const IR::Value& vaddr, const IR::Value& value_lo, const IR::Value& value_hi); + + void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRd, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2); + void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2, const IR::Value& word); + void CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm, const IR::Value& word1, const IR::Value& word2); + IR::Value CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2); + IR::Value CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm); + void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const IR::Value& address, bool has_option, u8 option); + void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const IR::Value& address, bool has_option, u8 option); +}; + +} // namespace IR +} // namespace Dynarmic diff --git a/src/frontend/A32/location_descriptor.h b/src/frontend/A32/location_descriptor.h index 51cdccd1..0b4fc4c5 100644 --- a/src/frontend/A32/location_descriptor.h +++ b/src/frontend/A32/location_descriptor.h @@ -33,10 +33,10 @@ public: : arm_pc(arm_pc), cpsr(cpsr.Value() & CPSR_MODE_MASK), fpscr(fpscr.Value() & FPSCR_MODE_MASK) {} /*implict*/ LocationDescriptor(const IR::LocationDescriptor& o) { - arm_pc = o.value >> 32; - cpsr.T(o.value & 1); - cpsr.E(o.value & 2); - fpscr = o.value & FPSCR_MODE_MASK; + arm_pc = o.Value() >> 32; + cpsr.T(o.Value() & 1); + cpsr.E(o.Value() & 2); + fpscr = o.Value() & FPSCR_MODE_MASK; } u32 PC() const { return arm_pc; } diff --git a/src/frontend/A32/translate/translate_arm.cpp b/src/frontend/A32/translate/translate_arm.cpp index 86c004d3..40c268bd 100644 --- a/src/frontend/A32/translate/translate_arm.cpp +++ b/src/frontend/A32/translate/translate_arm.cpp @@ -9,16 +9,16 @@ #include "common/assert.h" #include "frontend/A32/decoder/arm.h" #include "frontend/A32/decoder/vfp2.h" +#include "frontend/A32/location_descriptor.h" #include "frontend/A32/translate/translate.h" #include "frontend/A32/translate/translate_arm/translate_arm.h" #include "frontend/A32/types.h" #include "frontend/ir/basic_block.h" -#include "frontend/ir/location_descriptor.h" namespace Dynarmic { namespace A32 { -static bool CondCanContinue(ConditionalState cond_state, const IR::A32IREmitter& ir) { +static bool CondCanContinue(ConditionalState cond_state, const A32::IREmitter& ir) { ASSERT_MSG(cond_state != ConditionalState::Break, "Should never happen."); if (cond_state == ConditionalState::None) @@ -121,7 +121,7 @@ bool ArmTranslatorVisitor::UnpredictableInstruction() { return false; } -IR::A32IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in) { +A32::IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in) { switch (type) { case ShiftType::LSL: return ir.LogicalShiftLeft(value, ir.Imm8(imm5), carry_in); @@ -141,7 +141,7 @@ IR::A32IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitImmShift(IR::Value va return {}; } -IR::A32IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in) { +A32::IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in) { switch (type) { case ShiftType::LSL: return ir.LogicalShiftLeft(value, amount, carry_in); diff --git a/src/frontend/A32/translate/translate_arm/extension.cpp b/src/frontend/A32/translate/translate_arm/extension.cpp index 2fb2623c..e714425a 100644 --- a/src/frontend/A32/translate/translate_arm/extension.cpp +++ b/src/frontend/A32/translate/translate_arm/extension.cpp @@ -9,7 +9,7 @@ namespace Dynarmic { namespace A32 { -static IR::Value Rotate(IR::A32IREmitter& ir, Reg m, SignExtendRotation rotate) { +static IR::Value Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) { const u8 rotate_by = static_cast(static_cast(rotate) * 8); return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result; } diff --git a/src/frontend/A32/translate/translate_arm/load_store.cpp b/src/frontend/A32/translate/translate_arm/load_store.cpp index 3832f37d..c3a22aa6 100644 --- a/src/frontend/A32/translate/translate_arm/load_store.cpp +++ b/src/frontend/A32/translate/translate_arm/load_store.cpp @@ -41,7 +41,7 @@ bool ArmTranslatorVisitor::arm_STRT() { ASSERT_MSG(false, "System instructions unimplemented"); } -static IR::Value GetAddress(IR::A32IREmitter& ir, bool P, bool U, bool W, Reg n, IR::Value offset) { +static IR::Value GetAddress(A32::IREmitter& ir, bool P, bool U, bool W, Reg n, IR::Value offset) { const bool index = P; const bool add = U; const bool wback = !P || W; @@ -608,7 +608,7 @@ bool ArmTranslatorVisitor::arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n return true; } -static bool LDMHelper(IR::A32IREmitter& ir, bool W, Reg n, RegList list, IR::Value start_address, IR::Value writeback_address) { +static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::Value start_address, IR::Value writeback_address) { auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { @@ -686,7 +686,7 @@ bool ArmTranslatorVisitor::arm_LDM_eret() { return InterpretThisInstruction(); } -static bool STMHelper(IR::A32IREmitter& ir, bool W, Reg n, RegList list, IR::Value start_address, IR::Value writeback_address) { +static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::Value start_address, IR::Value writeback_address) { auto address = start_address; for (size_t i = 0; i <= 14; i++) { if (Common::Bit(i, list)) { diff --git a/src/frontend/A32/translate/translate_arm/saturated.cpp b/src/frontend/A32/translate/translate_arm/saturated.cpp index bc5b8a18..36fad32c 100644 --- a/src/frontend/A32/translate/translate_arm/saturated.cpp +++ b/src/frontend/A32/translate/translate_arm/saturated.cpp @@ -9,11 +9,11 @@ namespace Dynarmic { namespace A32 { -static IR::Value Pack2x16To1x32(IR::A32IREmitter& ir, IR::Value lo, IR::Value hi) { +static IR::Value Pack2x16To1x32(A32::IREmitter& ir, IR::Value lo, IR::Value hi) { return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result); } -static IR::Value MostSignificantHalf(IR::A32IREmitter& ir, IR::Value value) { +static IR::Value MostSignificantHalf(A32::IREmitter& ir, IR::Value value) { return ir.LeastSignificantHalf(ir.LogicalShiftRight(value, ir.Imm8(16), ir.Imm1(0)).result); } diff --git a/src/frontend/A32/translate/translate_arm/translate_arm.h b/src/frontend/A32/translate/translate_arm/translate_arm.h index 78f63bc7..4c220e2c 100644 --- a/src/frontend/A32/translate/translate_arm/translate_arm.h +++ b/src/frontend/A32/translate/translate_arm/translate_arm.h @@ -6,8 +6,8 @@ #pragma once -#include "frontend/ir/ir_emitter.h" -#include "frontend/ir/location_descriptor.h" +#include "frontend/A32/ir_emitter.h" +#include "frontend/A32/location_descriptor.h" namespace Dynarmic { namespace A32 { @@ -30,7 +30,7 @@ struct ArmTranslatorVisitor final { ASSERT_MSG(!descriptor.TFlag(), "The processor must be in Arm mode"); } - IR::A32IREmitter ir; + A32::IREmitter ir; ConditionalState cond_state = ConditionalState::None; bool ConditionPassed(Cond cond); @@ -62,8 +62,8 @@ struct ArmTranslatorVisitor final { return {imm32, carry_out}; } - IR::A32IREmitter::ResultAndCarry EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in); - IR::A32IREmitter::ResultAndCarry EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in); + A32::IREmitter::ResultAndCarry EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in); + A32::IREmitter::ResultAndCarry EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in); template bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn); template bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn); diff --git a/src/frontend/A32/translate/translate_thumb.cpp b/src/frontend/A32/translate/translate_thumb.cpp index d5d30490..2d5485b8 100644 --- a/src/frontend/A32/translate/translate_thumb.cpp +++ b/src/frontend/A32/translate/translate_thumb.cpp @@ -10,10 +10,10 @@ #include "common/bit_util.h" #include "frontend/A32/decoder/thumb16.h" #include "frontend/A32/decoder/thumb32.h" +#include "frontend/A32/ir_emitter.h" +#include "frontend/A32/location_descriptor.h" #include "frontend/A32/translate/translate.h" #include "frontend/A32/types.h" -#include "frontend/ir/ir_emitter.h" -#include "frontend/ir/location_descriptor.h" namespace Dynarmic { namespace A32 { @@ -27,7 +27,7 @@ struct ThumbTranslatorVisitor final { ASSERT_MSG(descriptor.TFlag(), "The processor must be in Thumb mode"); } - IR::A32IREmitter ir; + A32::IREmitter ir; bool InterpretThisInstruction() { ir.SetTerm(IR::Term::Interpret(ir.current_location)); diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 6925c9c6..126fe5cb 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -11,256 +11,110 @@ namespace Dynarmic { namespace IR { -void A32IREmitter::Unimplemented() { +void IREmitter::Unimplemented() { } -u32 A32IREmitter::PC() { - u32 offset = current_location.TFlag() ? 4 : 8; - return current_location.PC() + offset; -} - -u32 A32IREmitter::AlignPC(size_t alignment) { - u32 pc = PC(); - return static_cast(pc - pc % alignment); -} - -Value A32IREmitter::Imm1(bool imm1) { +Value IREmitter::Imm1(bool imm1) { return Value(imm1); } -Value A32IREmitter::Imm8(u8 imm8) { +Value IREmitter::Imm8(u8 imm8) { return Value(imm8); } -Value A32IREmitter::Imm32(u32 imm32) { +Value IREmitter::Imm32(u32 imm32) { return Value(imm32); } -Value A32IREmitter::Imm64(u64 imm64) { +Value IREmitter::Imm64(u64 imm64) { return Value(imm64); } -Value A32IREmitter::GetRegister(A32::Reg reg) { - if (reg == A32::Reg::PC) { - return Imm32(PC()); - } - return Inst(Opcode::GetRegister, { Value(reg) }); -} - -Value A32IREmitter::GetExtendedRegister(A32::ExtReg reg) { - if (A32::IsSingleExtReg(reg)) { - return Inst(Opcode::GetExtendedRegister32, {Value(reg)}); - } - - if (A32::IsDoubleExtReg(reg)) { - return Inst(Opcode::GetExtendedRegister64, {Value(reg)}); - } - - ASSERT_MSG(false, "Invalid reg."); -} - -void A32IREmitter::SetRegister(const A32::Reg reg, const Value& value) { - ASSERT(reg != A32::Reg::PC); - Inst(Opcode::SetRegister, { Value(reg), value }); -} - -void A32IREmitter::SetExtendedRegister(const A32::ExtReg reg, const Value& value) { - if (A32::IsSingleExtReg(reg)) { - Inst(Opcode::SetExtendedRegister32, {Value(reg), value}); - } else if (A32::IsDoubleExtReg(reg)) { - Inst(Opcode::SetExtendedRegister64, {Value(reg), value}); - } else { - ASSERT_MSG(false, "Invalid reg."); - } -} - -void A32IREmitter::ALUWritePC(const Value& value) { - // This behaviour is ARM version-dependent. - // The below implementation is for ARMv6k - BranchWritePC(value); -} - -void A32IREmitter::BranchWritePC(const Value& value) { - if (!current_location.TFlag()) { - auto new_pc = And(value, Imm32(0xFFFFFFFC)); - Inst(Opcode::SetRegister, { Value(A32::Reg::PC), new_pc }); - } else { - auto new_pc = And(value, Imm32(0xFFFFFFFE)); - Inst(Opcode::SetRegister, { Value(A32::Reg::PC), new_pc }); - } -} - -void A32IREmitter::BXWritePC(const Value& value) { - Inst(Opcode::BXWritePC, {value}); -} - -void A32IREmitter::LoadWritePC(const Value& value) { - // This behaviour is ARM version-dependent. - // The below implementation is for ARMv6k - BXWritePC(value); -} - -void A32IREmitter::CallSupervisor(const Value& value) { - Inst(Opcode::CallSupervisor, {value}); -} - -void A32IREmitter::PushRSB(const A32::LocationDescriptor& return_location) { - Inst(Opcode::PushRSB, {Value(return_location.UniqueHash())}); -} - -Value A32IREmitter::GetCpsr() { - return Inst(Opcode::GetCpsr, {}); -} - -void A32IREmitter::SetCpsr(const Value& value) { - Inst(Opcode::SetCpsr, {value}); -} - -void A32IREmitter::SetCpsrNZCV(const Value& value) { - Inst(Opcode::SetCpsrNZCV, {value}); -} - -void A32IREmitter::SetCpsrNZCVQ(const Value& value) { - Inst(Opcode::SetCpsrNZCVQ, {value}); -} - -Value A32IREmitter::GetCFlag() { - return Inst(Opcode::GetCFlag, {}); -} - -void A32IREmitter::SetNFlag(const Value& value) { - Inst(Opcode::SetNFlag, {value}); -} - -void A32IREmitter::SetZFlag(const Value& value) { - Inst(Opcode::SetZFlag, {value}); -} - -void A32IREmitter::SetCFlag(const Value& value) { - Inst(Opcode::SetCFlag, {value}); -} - -void A32IREmitter::SetVFlag(const Value& value) { - Inst(Opcode::SetVFlag, {value}); -} - -void A32IREmitter::OrQFlag(const Value& value) { - Inst(Opcode::OrQFlag, {value}); -} - -Value A32IREmitter::GetGEFlags() { - return Inst(Opcode::GetGEFlags, {}); -} - -void A32IREmitter::SetGEFlags(const Value& value) { - Inst(Opcode::SetGEFlags, {value}); -} - -void A32IREmitter::SetGEFlagsCompressed(const Value& value) { - Inst(Opcode::SetGEFlagsCompressed, {value}); -} - -Value A32IREmitter::GetFpscr() { - return Inst(Opcode::GetFpscr, {}); -} - -void A32IREmitter::SetFpscr(const Value& new_fpscr) { - Inst(Opcode::SetFpscr, {new_fpscr}); -} - -Value A32IREmitter::GetFpscrNZCV() { - return Inst(Opcode::GetFpscrNZCV, {}); -} - -void A32IREmitter::SetFpscrNZCV(const Value& new_fpscr_nzcv) { - Inst(Opcode::SetFpscrNZCV, {new_fpscr_nzcv}); -} - -Value A32IREmitter::Pack2x32To1x64(const Value& lo, const Value& hi) { +Value IREmitter::Pack2x32To1x64(const Value& lo, const Value& hi) { return Inst(Opcode::Pack2x32To1x64, {lo, hi}); } -Value A32IREmitter::LeastSignificantWord(const Value& value) { +Value IREmitter::LeastSignificantWord(const Value& value) { return Inst(Opcode::LeastSignificantWord, {value}); } -A32IREmitter::ResultAndCarry A32IREmitter::MostSignificantWord(const Value& value) { +IREmitter::ResultAndCarry IREmitter::MostSignificantWord(const Value& value) { auto result = Inst(Opcode::MostSignificantWord, {value}); auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); return {result, carry_out}; } -Value A32IREmitter::LeastSignificantHalf(const Value& value) { +Value IREmitter::LeastSignificantHalf(const Value& value) { return Inst(Opcode::LeastSignificantHalf, {value}); } -Value A32IREmitter::LeastSignificantByte(const Value& value) { +Value IREmitter::LeastSignificantByte(const Value& value) { return Inst(Opcode::LeastSignificantByte, {value}); } -Value A32IREmitter::MostSignificantBit(const Value& value) { +Value IREmitter::MostSignificantBit(const Value& value) { return Inst(Opcode::MostSignificantBit, {value}); } -Value A32IREmitter::IsZero(const Value& value) { +Value IREmitter::IsZero(const Value& value) { return Inst(Opcode::IsZero, {value}); } -Value A32IREmitter::IsZero64(const Value& value) { +Value IREmitter::IsZero64(const Value& value) { return Inst(Opcode::IsZero64, {value}); } -A32IREmitter::ResultAndCarry A32IREmitter::LogicalShiftLeft(const Value& value_in, const Value& shift_amount, const Value& carry_in) { +IREmitter::ResultAndCarry IREmitter::LogicalShiftLeft(const Value& value_in, const Value& shift_amount, const Value& carry_in) { auto result = Inst(Opcode::LogicalShiftLeft, {value_in, shift_amount, carry_in}); auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); return {result, carry_out}; } -A32IREmitter::ResultAndCarry A32IREmitter::LogicalShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) { +IREmitter::ResultAndCarry IREmitter::LogicalShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) { auto result = Inst(Opcode::LogicalShiftRight, {value_in, shift_amount, carry_in}); auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); return {result, carry_out}; } -Value A32IREmitter::LogicalShiftRight64(const Value& value_in, const Value& shift_amount) { +Value IREmitter::LogicalShiftRight64(const Value& value_in, const Value& shift_amount) { return Inst(Opcode::LogicalShiftRight64, {value_in, shift_amount}); } -A32IREmitter::ResultAndCarry A32IREmitter::ArithmeticShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) { +IREmitter::ResultAndCarry IREmitter::ArithmeticShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) { auto result = Inst(Opcode::ArithmeticShiftRight, {value_in, shift_amount, carry_in}); auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); return {result, carry_out}; } -A32IREmitter::ResultAndCarry A32IREmitter::RotateRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) { +IREmitter::ResultAndCarry IREmitter::RotateRight(const Value& value_in, const Value& shift_amount, const Value& carry_in) { auto result = Inst(Opcode::RotateRight, {value_in, shift_amount, carry_in}); auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); return {result, carry_out}; } -A32IREmitter::ResultAndCarry A32IREmitter::RotateRightExtended(const Value& value_in, const Value& carry_in) { +IREmitter::ResultAndCarry IREmitter::RotateRightExtended(const Value& value_in, const Value& carry_in) { auto result = Inst(Opcode::RotateRightExtended, {value_in, carry_in}); auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); return {result, carry_out}; } -A32IREmitter::ResultAndCarryAndOverflow A32IREmitter::AddWithCarry(const Value& a, const Value& b, const Value& carry_in) { +IREmitter::ResultAndCarryAndOverflow IREmitter::AddWithCarry(const Value& a, const Value& b, const Value& carry_in) { auto result = Inst(Opcode::AddWithCarry, {a, b, carry_in}); auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); auto overflow = Inst(Opcode::GetOverflowFromOp, {result}); return {result, carry_out, overflow}; } -Value A32IREmitter::Add(const Value& a, const Value& b) { +Value IREmitter::Add(const Value& a, const Value& b) { return Inst(Opcode::AddWithCarry, {a, b, Imm1(0)}); } -Value A32IREmitter::Add64(const Value& a, const Value& b) { +Value IREmitter::Add64(const Value& a, const Value& b) { return Inst(Opcode::Add64, {a, b}); } -A32IREmitter::ResultAndCarryAndOverflow A32IREmitter::SubWithCarry(const Value& a, const Value& b, const Value& carry_in) { +IREmitter::ResultAndCarryAndOverflow IREmitter::SubWithCarry(const Value& a, const Value& b, const Value& carry_in) { // This is equivalent to AddWithCarry(a, Not(b), carry_in). auto result = Inst(Opcode::SubWithCarry, {a, b, carry_in}); auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); @@ -268,578 +122,413 @@ A32IREmitter::ResultAndCarryAndOverflow A32IREmitter::SubWithCarry(const Value& return {result, carry_out, overflow}; } -Value A32IREmitter::Sub(const Value& a, const Value& b) { +Value IREmitter::Sub(const Value& a, const Value& b) { return Inst(Opcode::SubWithCarry, {a, b, Imm1(1)}); } -Value A32IREmitter::Sub64(const Value& a, const Value& b) { +Value IREmitter::Sub64(const Value& a, const Value& b) { return Inst(Opcode::Sub64, {a, b}); } -Value A32IREmitter::Mul(const Value& a, const Value& b) { +Value IREmitter::Mul(const Value& a, const Value& b) { return Inst(Opcode::Mul, {a, b}); } -Value A32IREmitter::Mul64(const Value& a, const Value& b) { +Value IREmitter::Mul64(const Value& a, const Value& b) { return Inst(Opcode::Mul64, {a, b}); } -Value A32IREmitter::And(const Value& a, const Value& b) { +Value IREmitter::And(const Value& a, const Value& b) { return Inst(Opcode::And, {a, b}); } -Value A32IREmitter::Eor(const Value& a, const Value& b) { +Value IREmitter::Eor(const Value& a, const Value& b) { return Inst(Opcode::Eor, {a, b}); } -Value A32IREmitter::Or(const Value& a, const Value& b) { +Value IREmitter::Or(const Value& a, const Value& b) { return Inst(Opcode::Or, {a, b}); } -Value A32IREmitter::Not(const Value& a) { +Value IREmitter::Not(const Value& a) { return Inst(Opcode::Not, {a}); } -Value A32IREmitter::SignExtendWordToLong(const Value& a) { +Value IREmitter::SignExtendWordToLong(const Value& a) { return Inst(Opcode::SignExtendWordToLong, {a}); } -Value A32IREmitter::SignExtendHalfToWord(const Value& a) { +Value IREmitter::SignExtendHalfToWord(const Value& a) { return Inst(Opcode::SignExtendHalfToWord, {a}); } -Value A32IREmitter::SignExtendByteToWord(const Value& a) { +Value IREmitter::SignExtendByteToWord(const Value& a) { return Inst(Opcode::SignExtendByteToWord, {a}); } -Value A32IREmitter::ZeroExtendWordToLong(const Value& a) { +Value IREmitter::ZeroExtendWordToLong(const Value& a) { return Inst(Opcode::ZeroExtendWordToLong, {a}); } -Value A32IREmitter::ZeroExtendHalfToWord(const Value& a) { +Value IREmitter::ZeroExtendHalfToWord(const Value& a) { return Inst(Opcode::ZeroExtendHalfToWord, {a}); } -Value A32IREmitter::ZeroExtendByteToWord(const Value& a) { +Value IREmitter::ZeroExtendByteToWord(const Value& a) { return Inst(Opcode::ZeroExtendByteToWord, {a}); } -Value A32IREmitter::ByteReverseWord(const Value& a) { +Value IREmitter::ByteReverseWord(const Value& a) { return Inst(Opcode::ByteReverseWord, {a}); } -Value A32IREmitter::ByteReverseHalf(const Value& a) { +Value IREmitter::ByteReverseHalf(const Value& a) { return Inst(Opcode::ByteReverseHalf, {a}); } -Value A32IREmitter::ByteReverseDual(const Value& a) { +Value IREmitter::ByteReverseDual(const Value& a) { return Inst(Opcode::ByteReverseDual, {a}); } -Value A32IREmitter::CountLeadingZeros(const Value& a) { +Value IREmitter::CountLeadingZeros(const Value& a) { return Inst(Opcode::CountLeadingZeros, {a}); } -A32IREmitter::ResultAndOverflow A32IREmitter::SignedSaturatedAdd(const Value& a, const Value& b) { +IREmitter::ResultAndOverflow IREmitter::SignedSaturatedAdd(const Value& a, const Value& b) { auto result = Inst(Opcode::SignedSaturatedAdd, {a, b}); auto overflow = Inst(Opcode::GetOverflowFromOp, {result}); return {result, overflow}; } -A32IREmitter::ResultAndOverflow A32IREmitter::SignedSaturatedSub(const Value& a, const Value& b) { +IREmitter::ResultAndOverflow IREmitter::SignedSaturatedSub(const Value& a, const Value& b) { auto result = Inst(Opcode::SignedSaturatedSub, {a, b}); auto overflow = Inst(Opcode::GetOverflowFromOp, {result}); return {result, overflow}; } -A32IREmitter::ResultAndOverflow A32IREmitter::UnsignedSaturation(const Value& a, size_t bit_size_to_saturate_to) { +IREmitter::ResultAndOverflow IREmitter::UnsignedSaturation(const Value& a, size_t bit_size_to_saturate_to) { ASSERT(bit_size_to_saturate_to <= 31); auto result = Inst(Opcode::UnsignedSaturation, {a, Imm8(static_cast(bit_size_to_saturate_to))}); auto overflow = Inst(Opcode::GetOverflowFromOp, {result}); return {result, overflow}; } -A32IREmitter::ResultAndOverflow A32IREmitter::SignedSaturation(const Value& a, size_t bit_size_to_saturate_to) { +IREmitter::ResultAndOverflow IREmitter::SignedSaturation(const Value& a, size_t bit_size_to_saturate_to) { ASSERT(bit_size_to_saturate_to >= 1 && bit_size_to_saturate_to <= 32); auto result = Inst(Opcode::SignedSaturation, {a, Imm8(static_cast(bit_size_to_saturate_to))}); auto overflow = Inst(Opcode::GetOverflowFromOp, {result}); return {result, overflow}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedAddU8(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedAddU8(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedAddU8, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedAddS8(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedAddS8(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedAddS8, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedAddU16(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedAddU16(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedAddU16, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedAddS16(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedAddS16(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedAddS16, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedSubU8(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedSubU8(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedSubU8, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedSubS8(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedSubS8(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedSubS8, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedSubU16(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedSubU16(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedSubU16, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedSubS16(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedSubS16(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedSubS16, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedAddSubU16(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedAddSubU16(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedAddSubU16, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedAddSubS16(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedAddSubS16(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedAddSubS16, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedSubAddU16(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedSubAddU16(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedSubAddU16, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -A32IREmitter::ResultAndGE A32IREmitter::PackedSubAddS16(const Value& a, const Value& b) { +IREmitter::ResultAndGE IREmitter::PackedSubAddS16(const Value& a, const Value& b) { auto result = Inst(Opcode::PackedSubAddS16, {a, b}); auto ge = Inst(Opcode::GetGEFromOp, {result}); return {result, ge}; } -Value A32IREmitter::PackedHalvingAddU8(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingAddU8(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingAddU8, {a, b}); } -Value A32IREmitter::PackedHalvingAddS8(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingAddS8(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingAddS8, {a, b}); } -Value A32IREmitter::PackedHalvingSubU8(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingSubU8(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingSubU8, {a, b}); } -Value A32IREmitter::PackedHalvingSubS8(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingSubS8(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingSubS8, {a, b}); } -Value A32IREmitter::PackedHalvingAddU16(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingAddU16(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingAddU16, {a, b}); } -Value A32IREmitter::PackedHalvingAddS16(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingAddS16(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingAddS16, {a, b}); } -Value A32IREmitter::PackedHalvingSubU16(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingSubU16(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingSubU16, {a, b}); } -Value A32IREmitter::PackedHalvingSubS16(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingSubS16(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingSubS16, {a, b}); } -Value A32IREmitter::PackedHalvingAddSubU16(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingAddSubU16(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingAddSubU16, {a, b}); } -Value A32IREmitter::PackedHalvingAddSubS16(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingAddSubS16(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingAddSubS16, {a, b}); } -Value A32IREmitter::PackedHalvingSubAddU16(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingSubAddU16(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingSubAddU16, {a, b}); } -Value A32IREmitter::PackedHalvingSubAddS16(const Value& a, const Value& b) { +Value IREmitter::PackedHalvingSubAddS16(const Value& a, const Value& b) { return Inst(Opcode::PackedHalvingSubAddS16, {a, b}); } -Value A32IREmitter::PackedSaturatedAddU8(const Value& a, const Value& b) { +Value IREmitter::PackedSaturatedAddU8(const Value& a, const Value& b) { return Inst(Opcode::PackedSaturatedAddU8, {a, b}); } -Value A32IREmitter::PackedSaturatedAddS8(const Value& a, const Value& b) { +Value IREmitter::PackedSaturatedAddS8(const Value& a, const Value& b) { return Inst(Opcode::PackedSaturatedAddS8, {a, b}); } -Value A32IREmitter::PackedSaturatedSubU8(const Value& a, const Value& b) { +Value IREmitter::PackedSaturatedSubU8(const Value& a, const Value& b) { return Inst(Opcode::PackedSaturatedSubU8, {a, b}); } -Value A32IREmitter::PackedSaturatedSubS8(const Value& a, const Value& b) { +Value IREmitter::PackedSaturatedSubS8(const Value& a, const Value& b) { return Inst(Opcode::PackedSaturatedSubS8, {a, b}); } -Value A32IREmitter::PackedSaturatedAddU16(const Value& a, const Value& b) { +Value IREmitter::PackedSaturatedAddU16(const Value& a, const Value& b) { return Inst(Opcode::PackedSaturatedAddU16, {a, b}); } -Value A32IREmitter::PackedSaturatedAddS16(const Value& a, const Value& b) { +Value IREmitter::PackedSaturatedAddS16(const Value& a, const Value& b) { return Inst(Opcode::PackedSaturatedAddS16, {a, b}); } -Value A32IREmitter::PackedSaturatedSubU16(const Value& a, const Value& b) { +Value IREmitter::PackedSaturatedSubU16(const Value& a, const Value& b) { return Inst(Opcode::PackedSaturatedSubU16, {a, b}); } -Value A32IREmitter::PackedSaturatedSubS16(const Value& a, const Value& b) { +Value IREmitter::PackedSaturatedSubS16(const Value& a, const Value& b) { return Inst(Opcode::PackedSaturatedSubS16, {a, b}); } -Value A32IREmitter::PackedAbsDiffSumS8(const Value& a, const Value& b) { +Value IREmitter::PackedAbsDiffSumS8(const Value& a, const Value& b) { return Inst(Opcode::PackedAbsDiffSumS8, {a, b}); } -Value A32IREmitter::PackedSelect(const Value& ge, const Value& a, const Value& b) { +Value IREmitter::PackedSelect(const Value& ge, const Value& a, const Value& b) { return Inst(Opcode::PackedSelect, {ge, a, b}); } -Value A32IREmitter::TransferToFP32(const Value& a) { +Value IREmitter::TransferToFP32(const Value& a) { return Inst(Opcode::TransferToFP32, {a}); } -Value A32IREmitter::TransferToFP64(const Value& a) { +Value IREmitter::TransferToFP64(const Value& a) { return Inst(Opcode::TransferToFP64, {a}); } -Value A32IREmitter::TransferFromFP32(const Value& a) { +Value IREmitter::TransferFromFP32(const Value& a) { return Inst(Opcode::TransferFromFP32, {a}); } -Value A32IREmitter::TransferFromFP64(const Value& a) { +Value IREmitter::TransferFromFP64(const Value& a) { return Inst(Opcode::TransferFromFP64, {a}); } -Value A32IREmitter::FPAbs32(const Value& a) { +Value IREmitter::FPAbs32(const Value& a) { return Inst(Opcode::FPAbs32, {a}); } -Value A32IREmitter::FPAbs64(const Value& a) { +Value IREmitter::FPAbs64(const Value& a) { return Inst(Opcode::FPAbs64, {a}); } -Value A32IREmitter::FPAdd32(const Value& a, const Value& b, bool fpscr_controlled) { +Value IREmitter::FPAdd32(const Value& a, const Value& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPAdd32, {a, b}); } -Value A32IREmitter::FPAdd64(const Value& a, const Value& b, bool fpscr_controlled) { +Value IREmitter::FPAdd64(const Value& a, const Value& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPAdd64, {a, b}); } -void A32IREmitter::FPCompare32(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) { +void IREmitter::FPCompare32(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) { ASSERT(fpscr_controlled); Inst(Opcode::FPCompare32, {a, b, Imm1(exc_on_qnan)}); } -void A32IREmitter::FPCompare64(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) { +void IREmitter::FPCompare64(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) { ASSERT(fpscr_controlled); Inst(Opcode::FPCompare64, {a, b, Imm1(exc_on_qnan)}); } -Value A32IREmitter::FPDiv32(const Value& a, const Value& b, bool fpscr_controlled) { +Value IREmitter::FPDiv32(const Value& a, const Value& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPDiv32, {a, b}); } -Value A32IREmitter::FPDiv64(const Value& a, const Value& b, bool fpscr_controlled) { +Value IREmitter::FPDiv64(const Value& a, const Value& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPDiv64, {a, b}); } -Value A32IREmitter::FPMul32(const Value& a, const Value& b, bool fpscr_controlled) { +Value IREmitter::FPMul32(const Value& a, const Value& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPMul32, {a, b}); } -Value A32IREmitter::FPMul64(const Value& a, const Value& b, bool fpscr_controlled) { +Value IREmitter::FPMul64(const Value& a, const Value& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPMul64, {a, b}); } -Value A32IREmitter::FPNeg32(const Value& a) { +Value IREmitter::FPNeg32(const Value& a) { return Inst(Opcode::FPNeg32, {a}); } -Value A32IREmitter::FPNeg64(const Value& a) { +Value IREmitter::FPNeg64(const Value& a) { return Inst(Opcode::FPNeg64, {a}); } -Value A32IREmitter::FPSqrt32(const Value& a) { +Value IREmitter::FPSqrt32(const Value& a) { return Inst(Opcode::FPSqrt32, {a}); } -Value A32IREmitter::FPSqrt64(const Value& a) { +Value IREmitter::FPSqrt64(const Value& a) { return Inst(Opcode::FPSqrt64, {a}); } -Value A32IREmitter::FPSub32(const Value& a, const Value& b, bool fpscr_controlled) { +Value IREmitter::FPSub32(const Value& a, const Value& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPSub32, {a, b}); } -Value A32IREmitter::FPSub64(const Value& a, const Value& b, bool fpscr_controlled) { +Value IREmitter::FPSub64(const Value& a, const Value& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPSub64, {a, b}); } -Value A32IREmitter::FPDoubleToSingle(const Value& a, bool fpscr_controlled) { +Value IREmitter::FPDoubleToSingle(const Value& a, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPDoubleToSingle, {a}); } -Value A32IREmitter::FPSingleToDouble(const Value& a, bool fpscr_controlled) { +Value IREmitter::FPSingleToDouble(const Value& a, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPSingleToDouble, {a}); } -Value A32IREmitter::FPSingleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { +Value IREmitter::FPSingleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPSingleToS32, {a, Imm1(round_towards_zero)}); } -Value A32IREmitter::FPSingleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { +Value IREmitter::FPSingleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPSingleToU32, {a, Imm1(round_towards_zero)}); } -Value A32IREmitter::FPDoubleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { +Value IREmitter::FPDoubleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPDoubleToS32, {a, Imm1(round_towards_zero)}); } -Value A32IREmitter::FPDoubleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { +Value IREmitter::FPDoubleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPDoubleToU32, {a, Imm1(round_towards_zero)}); } -Value A32IREmitter::FPS32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) { +Value IREmitter::FPS32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPS32ToSingle, {a, Imm1(round_to_nearest)}); } -Value A32IREmitter::FPU32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) { +Value IREmitter::FPU32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPU32ToSingle, {a, Imm1(round_to_nearest)}); } -Value A32IREmitter::FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) { +Value IREmitter::FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPS32ToDouble, {a, Imm1(round_to_nearest)}); } -Value A32IREmitter::FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) { +Value IREmitter::FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) { ASSERT(fpscr_controlled); return Inst(Opcode::FPU32ToDouble, {a, Imm1(round_to_nearest)}); } -void A32IREmitter::ClearExclusive() { - Inst(Opcode::ClearExclusive, {}); -} - -void A32IREmitter::SetExclusive(const Value& vaddr, size_t byte_size) { - ASSERT(byte_size == 1 || byte_size == 2 || byte_size == 4 || byte_size == 8 || byte_size == 16); - Inst(Opcode::SetExclusive, {vaddr, Imm8(u8(byte_size))}); -} - -Value A32IREmitter::ReadMemory8(const Value& vaddr) { - return Inst(Opcode::ReadMemory8, {vaddr}); -} - -Value A32IREmitter::ReadMemory16(const Value& vaddr) { - auto value = Inst(Opcode::ReadMemory16, {vaddr}); - return current_location.EFlag() ? ByteReverseHalf(value) : value; -} - -Value A32IREmitter::ReadMemory32(const Value& vaddr) { - auto value = Inst(Opcode::ReadMemory32, {vaddr}); - return current_location.EFlag() ? ByteReverseWord(value) : value; -} - -Value A32IREmitter::ReadMemory64(const Value& vaddr) { - auto value = Inst(Opcode::ReadMemory64, {vaddr}); - return current_location.EFlag() ? ByteReverseDual(value) : value; -} - -void A32IREmitter::WriteMemory8(const Value& vaddr, const Value& value) { - Inst(Opcode::WriteMemory8, {vaddr, value}); -} - -void A32IREmitter::WriteMemory16(const Value& vaddr, const Value& value) { - if (current_location.EFlag()) { - auto v = ByteReverseHalf(value); - Inst(Opcode::WriteMemory16, {vaddr, v}); - } else { - Inst(Opcode::WriteMemory16, {vaddr, value}); - } -} - -void A32IREmitter::WriteMemory32(const Value& vaddr, const Value& value) { - if (current_location.EFlag()) { - auto v = ByteReverseWord(value); - Inst(Opcode::WriteMemory32, {vaddr, v}); - } else { - Inst(Opcode::WriteMemory32, {vaddr, value}); - } -} - -void A32IREmitter::WriteMemory64(const Value& vaddr, const Value& value) { - if (current_location.EFlag()) { - auto v = ByteReverseDual(value); - Inst(Opcode::WriteMemory64, {vaddr, v}); - } else { - Inst(Opcode::WriteMemory64, {vaddr, value}); - } -} - -Value A32IREmitter::ExclusiveWriteMemory8(const Value& vaddr, const Value& value) { - return Inst(Opcode::ExclusiveWriteMemory8, {vaddr, value}); -} - -Value A32IREmitter::ExclusiveWriteMemory16(const Value& vaddr, const Value& value) { - if (current_location.EFlag()) { - auto v = ByteReverseHalf(value); - return Inst(Opcode::ExclusiveWriteMemory16, {vaddr, v}); - } else { - return Inst(Opcode::ExclusiveWriteMemory16, {vaddr, value}); - } -} - -Value A32IREmitter::ExclusiveWriteMemory32(const Value& vaddr, const Value& value) { - if (current_location.EFlag()) { - auto v = ByteReverseWord(value); - return Inst(Opcode::ExclusiveWriteMemory32, {vaddr, v}); - } else { - return Inst(Opcode::ExclusiveWriteMemory32, {vaddr, value}); - } -} - -Value A32IREmitter::ExclusiveWriteMemory64(const Value& vaddr, const Value& value_lo, const Value& value_hi) { - if (current_location.EFlag()) { - auto vlo = ByteReverseWord(value_lo); - auto vhi = ByteReverseWord(value_hi); - return Inst(Opcode::ExclusiveWriteMemory64, {vaddr, vlo, vhi}); - } else { - return Inst(Opcode::ExclusiveWriteMemory64, {vaddr, value_lo, value_hi}); - } -} - -void A32IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRd, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2) { - ASSERT(coproc_no <= 15); - std::array coproc_info{static_cast(coproc_no), - static_cast(two ? 1 : 0), - static_cast(opc1), - static_cast(CRd), - static_cast(CRn), - static_cast(CRm), - static_cast(opc2)}; - Inst(Opcode::CoprocInternalOperation, {Value(coproc_info)}); -} - -void A32IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2, const Value& word) { - ASSERT(coproc_no <= 15); - std::array coproc_info{static_cast(coproc_no), - static_cast(two ? 1 : 0), - static_cast(opc1), - static_cast(CRn), - static_cast(CRm), - static_cast(opc2)}; - Inst(Opcode::CoprocSendOneWord, {Value(coproc_info), word}); -} - -void A32IREmitter::CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm, const Value& word1, const Value& word2) { - ASSERT(coproc_no <= 15); - std::array coproc_info{static_cast(coproc_no), - static_cast(two ? 1 : 0), - static_cast(opc), - static_cast(CRm)}; - Inst(Opcode::CoprocSendTwoWords, {Value(coproc_info), word1, word2}); -} - -Value A32IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2) { - ASSERT(coproc_no <= 15); - std::array coproc_info{static_cast(coproc_no), - static_cast(two ? 1 : 0), - static_cast(opc1), - static_cast(CRn), - static_cast(CRm), - static_cast(opc2)}; - return Inst(Opcode::CoprocGetOneWord, {Value(coproc_info)}); -} - -Value A32IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm) { - ASSERT(coproc_no <= 15); - std::array coproc_info{static_cast(coproc_no), - static_cast(two ? 1 : 0), - static_cast(opc), - static_cast(CRm)}; - return Inst(Opcode::CoprocGetTwoWords, {Value(coproc_info)}); -} - -void A32IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const Value& address, bool has_option, u8 option) { - ASSERT(coproc_no <= 15); - std::array coproc_info{static_cast(coproc_no), - static_cast(two ? 1 : 0), - static_cast(long_transfer ? 1 : 0), - static_cast(CRd), - static_cast(has_option ? 1 : 0), - static_cast(option)}; - Inst(Opcode::CoprocLoadWords, {Value(coproc_info), address}); -} - -void A32IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const Value& address, bool has_option, u8 option) { - ASSERT(coproc_no <= 15); - std::array coproc_info{static_cast(coproc_no), - static_cast(two ? 1 : 0), - static_cast(long_transfer ? 1 : 0), - static_cast(CRd), - static_cast(has_option ? 1 : 0), - static_cast(option)}; - Inst(Opcode::CoprocStoreWords, {Value(coproc_info), address}); -} - -void A32IREmitter::Breakpoint() { +void IREmitter::Breakpoint() { Inst(Opcode::Breakpoint, {}); } -void A32IREmitter::SetTerm(const Terminal& terminal) { +void IREmitter::SetTerm(const Terminal& terminal) { block.SetTerminal(terminal); } -Value A32IREmitter::Inst(Opcode op, std::initializer_list args) { +Value IREmitter::Inst(Opcode op, std::initializer_list args) { block.AppendNewInst(op, args); return Value(&block.back()); } diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 7a78431d..b0d65f36 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -11,8 +11,6 @@ #include #include "common/common_types.h" -#include "frontend/A32/location_descriptor.h" -#include "frontend/A32/types.h" #include "frontend/ir/basic_block.h" #include "frontend/ir/location_descriptor.h" #include "frontend/ir/terminal.h" @@ -35,12 +33,11 @@ enum class Opcode; * `block` is the resulting block. * The user of this class updates `current_location` as appropriate. */ -class A32IREmitter { +class IREmitter { public: - explicit A32IREmitter(A32::LocationDescriptor descriptor) : block(descriptor), current_location(descriptor) {} + explicit IREmitter(IR::LocationDescriptor descriptor) : block(descriptor) {} Block block; - A32::LocationDescriptor current_location; struct ResultAndCarry { Value result; @@ -64,45 +61,12 @@ public: }; void Unimplemented(); - u32 PC(); - u32 AlignPC(size_t alignment); Value Imm1(bool value); Value Imm8(u8 value); Value Imm32(u32 value); Value Imm64(u64 value); - Value GetRegister(A32::Reg source_reg); - Value GetExtendedRegister(A32::ExtReg source_reg); - void SetRegister(const A32::Reg dest_reg, const Value& value); - void SetExtendedRegister(const A32::ExtReg dest_reg, const Value& value); - - void ALUWritePC(const Value& value); - void BranchWritePC(const Value& value); - void BXWritePC(const Value& value); - void LoadWritePC(const Value& value); - void CallSupervisor(const Value& value); - void PushRSB(const A32::LocationDescriptor& return_location); - - Value GetCpsr(); - void SetCpsr(const Value& value); - void SetCpsrNZCV(const Value& value); - void SetCpsrNZCVQ(const Value& value); - Value GetCFlag(); - void SetNFlag(const Value& value); - void SetZFlag(const Value& value); - void SetCFlag(const Value& value); - void SetVFlag(const Value& value); - void OrQFlag(const Value& value); - Value GetGEFlags(); - void SetGEFlags(const Value& value); - void SetGEFlagsCompressed(const Value& value); - - Value GetFpscr(); - void SetFpscr(const Value& new_fpscr); - Value GetFpscrNZCV(); - void SetFpscrNZCV(const Value& new_fpscr_nzcv); - Value Pack2x32To1x64(const Value& lo, const Value& hi); Value LeastSignificantWord(const Value& value); ResultAndCarry MostSignificantWord(const Value& value); @@ -212,34 +176,11 @@ public: Value FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled); Value FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled); - void ClearExclusive(); - void SetExclusive(const Value& vaddr, size_t byte_size); - Value ReadMemory8(const Value& vaddr); - Value ReadMemory16(const Value& vaddr); - Value ReadMemory32(const Value& vaddr); - Value ReadMemory64(const Value& vaddr); - void WriteMemory8(const Value& vaddr, const Value& value); - void WriteMemory16(const Value& vaddr, const Value& value); - void WriteMemory32(const Value& vaddr, const Value& value); - void WriteMemory64(const Value& vaddr, const Value& value); - Value ExclusiveWriteMemory8(const Value& vaddr, const Value& value); - Value ExclusiveWriteMemory16(const Value& vaddr, const Value& value); - Value ExclusiveWriteMemory32(const Value& vaddr, const Value& value); - Value ExclusiveWriteMemory64(const Value& vaddr, const Value& value_lo, const Value& value_hi); - - void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRd, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2); - void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2, const Value& word); - void CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm, const Value& word1, const Value& word2); - Value CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, A32::CoprocReg CRn, A32::CoprocReg CRm, size_t opc2); - Value CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm); - void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const Value& address, bool has_option, u8 option); - void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, A32::CoprocReg CRd, const Value& address, bool has_option, u8 option); - void Breakpoint(); void SetTerm(const Terminal& terminal); -private: +protected: Value Inst(Opcode op, std::initializer_list args); }; diff --git a/src/frontend/ir/location_descriptor.cpp b/src/frontend/ir/location_descriptor.cpp index 8c36be92..0c18c98a 100644 --- a/src/frontend/ir/location_descriptor.cpp +++ b/src/frontend/ir/location_descriptor.cpp @@ -13,7 +13,7 @@ namespace Dynarmic { namespace IR { std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) { - o << fmt::format("{{{{}}}}", descriptor.value); + o << fmt::format("{{{{}}}}", descriptor.Value()); return o; } diff --git a/src/frontend/ir/location_descriptor.h b/src/frontend/ir/location_descriptor.h index 7d222855..edc0318d 100644 --- a/src/frontend/ir/location_descriptor.h +++ b/src/frontend/ir/location_descriptor.h @@ -15,14 +15,19 @@ namespace IR { class LocationDescriptor { public: + explicit LocationDescriptor(u64 value) : value(value) {} + bool operator == (const LocationDescriptor& o) const { - return value == o.value; + return value == o.Value(); } bool operator != (const LocationDescriptor& o) const { return !operator==(o); } + u64 Value() const { return value; } + +private: u64 value; }; @@ -35,13 +40,13 @@ namespace std { template <> struct less { bool operator()(const Dynarmic::IR::LocationDescriptor& x, const Dynarmic::IR::LocationDescriptor& y) const { - return x.value < y.value; + return x.Value() < y.Value(); } }; template <> struct hash { size_t operator()(const Dynarmic::IR::LocationDescriptor& x) const { - return std::hash()(x.value); + return std::hash()(x.Value()); } }; } // namespace std