From f61da0b5a9cbf1dfce7e370e5fbb600858d31cb9 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Fri, 5 Jan 2018 21:47:23 +0000 Subject: [PATCH] IR: Compile-time type-checking of IR --- src/frontend/A32/ir_emitter.cpp | 200 +++---- src/frontend/A32/ir_emitter.h | 96 ++-- src/frontend/A32/translate/translate_arm.cpp | 4 +- .../A32/translate/translate_arm/extension.cpp | 2 +- .../translate/translate_arm/load_store.cpp | 6 +- .../A32/translate/translate_arm/multiply.cpp | 6 +- .../A32/translate/translate_arm/saturated.cpp | 4 +- .../translate/translate_arm/translate_arm.h | 8 +- .../A32/translate/translate_arm/vfp2.cpp | 164 +++--- src/frontend/ir/ir_emitter.cpp | 493 +++++++++--------- src/frontend/ir/ir_emitter.h | 268 +++++----- src/frontend/ir/opcodes.h | 36 +- src/frontend/ir/value.h | 28 +- 13 files changed, 697 insertions(+), 618 deletions(-) diff --git a/src/frontend/A32/ir_emitter.cpp b/src/frontend/A32/ir_emitter.cpp index 28b6a3ec..ae829847 100644 --- a/src/frontend/A32/ir_emitter.cpp +++ b/src/frontend/A32/ir_emitter.cpp @@ -23,230 +23,230 @@ u32 IREmitter::AlignPC(size_t alignment) { return static_cast(pc - pc % alignment); } -IR::Value IREmitter::GetRegister(A32::Reg reg) { +IR::U32 IREmitter::GetRegister(Reg reg) { if (reg == A32::Reg::PC) { return Imm32(PC()); } - return Inst(Opcode::A32GetRegister, { IR::Value(reg) }); + return Inst(Opcode::A32GetRegister, IR::Value(reg)); } -IR::Value IREmitter::GetExtendedRegister(A32::ExtReg reg) { +IR::F32F64 IREmitter::GetExtendedRegister(ExtReg reg) { if (A32::IsSingleExtReg(reg)) { - return Inst(Opcode::A32GetExtendedRegister32, {IR::Value(reg)}); + return Inst(Opcode::A32GetExtendedRegister32, IR::Value(reg)); } if (A32::IsDoubleExtReg(reg)) { - return Inst(Opcode::A32GetExtendedRegister64, {IR::Value(reg)}); + return Inst(Opcode::A32GetExtendedRegister64, IR::Value(reg)); } ASSERT_MSG(false, "Invalid reg."); } -void IREmitter::SetRegister(const A32::Reg reg, const IR::Value& value) { +void IREmitter::SetRegister(const Reg reg, const IR::U32& value) { ASSERT(reg != A32::Reg::PC); - Inst(Opcode::A32SetRegister, { IR::Value(reg), value }); + Inst(Opcode::A32SetRegister, IR::Value(reg), value); } -void IREmitter::SetExtendedRegister(const A32::ExtReg reg, const IR::Value& value) { +void IREmitter::SetExtendedRegister(const ExtReg reg, const IR::F32F64& value) { if (A32::IsSingleExtReg(reg)) { - Inst(Opcode::A32SetExtendedRegister32, {IR::Value(reg), value}); + Inst(Opcode::A32SetExtendedRegister32, IR::Value(reg), value); } else if (A32::IsDoubleExtReg(reg)) { - Inst(Opcode::A32SetExtendedRegister64, {IR::Value(reg), value}); + Inst(Opcode::A32SetExtendedRegister64, IR::Value(reg), value); } else { ASSERT_MSG(false, "Invalid reg."); } } -void IREmitter::ALUWritePC(const IR::Value& value) { +void IREmitter::ALUWritePC(const IR::U32& value) { // This behaviour is ARM version-dependent. // The below implementation is for ARMv6k BranchWritePC(value); } -void IREmitter::BranchWritePC(const IR::Value& value) { +void IREmitter::BranchWritePC(const IR::U32& value) { if (!current_location.TFlag()) { auto new_pc = And(value, Imm32(0xFFFFFFFC)); - Inst(Opcode::A32SetRegister, { IR::Value(A32::Reg::PC), new_pc }); + Inst(Opcode::A32SetRegister, IR::Value(A32::Reg::PC), new_pc); } else { auto new_pc = And(value, Imm32(0xFFFFFFFE)); - Inst(Opcode::A32SetRegister, { IR::Value(A32::Reg::PC), new_pc }); + Inst(Opcode::A32SetRegister, IR::Value(A32::Reg::PC), new_pc); } } -void IREmitter::BXWritePC(const IR::Value& value) { - Inst(Opcode::A32BXWritePC, {value}); +void IREmitter::BXWritePC(const IR::U32& value) { + Inst(Opcode::A32BXWritePC, value); } -void IREmitter::LoadWritePC(const IR::Value& value) { +void IREmitter::LoadWritePC(const IR::U32& value) { // This behaviour is ARM version-dependent. // The below implementation is for ARMv6k BXWritePC(value); } -void IREmitter::CallSupervisor(const IR::Value& value) { - Inst(Opcode::A32CallSupervisor, {value}); +void IREmitter::CallSupervisor(const IR::U32& value) { + Inst(Opcode::A32CallSupervisor, value); } -IR::Value IREmitter::GetCpsr() { - return Inst(Opcode::A32GetCpsr, {}); +IR::U32 IREmitter::GetCpsr() { + return Inst(Opcode::A32GetCpsr); } -void IREmitter::SetCpsr(const IR::Value& value) { - Inst(Opcode::A32SetCpsr, {value}); +void IREmitter::SetCpsr(const IR::U32& value) { + Inst(Opcode::A32SetCpsr, value); } -void IREmitter::SetCpsrNZCV(const IR::Value& value) { - Inst(Opcode::A32SetCpsrNZCV, {value}); +void IREmitter::SetCpsrNZCV(const IR::U32& value) { + Inst(Opcode::A32SetCpsrNZCV, value); } -void IREmitter::SetCpsrNZCVQ(const IR::Value& value) { - Inst(Opcode::A32SetCpsrNZCVQ, {value}); +void IREmitter::SetCpsrNZCVQ(const IR::U32& value) { + Inst(Opcode::A32SetCpsrNZCVQ, value); } -IR::Value IREmitter::GetCFlag() { - return Inst(Opcode::A32GetCFlag, {}); +IR::U1 IREmitter::GetCFlag() { + return Inst(Opcode::A32GetCFlag); } -void IREmitter::SetNFlag(const IR::Value& value) { - Inst(Opcode::A32SetNFlag, {value}); +void IREmitter::SetNFlag(const IR::U1& value) { + Inst(Opcode::A32SetNFlag, value); } -void IREmitter::SetZFlag(const IR::Value& value) { - Inst(Opcode::A32SetZFlag, {value}); +void IREmitter::SetZFlag(const IR::U1& value) { + Inst(Opcode::A32SetZFlag, value); } -void IREmitter::SetCFlag(const IR::Value& value) { - Inst(Opcode::A32SetCFlag, {value}); +void IREmitter::SetCFlag(const IR::U1& value) { + Inst(Opcode::A32SetCFlag, value); } -void IREmitter::SetVFlag(const IR::Value& value) { - Inst(Opcode::A32SetVFlag, {value}); +void IREmitter::SetVFlag(const IR::U1& value) { + Inst(Opcode::A32SetVFlag, value); } -void IREmitter::OrQFlag(const IR::Value& value) { - Inst(Opcode::A32OrQFlag, {value}); +void IREmitter::OrQFlag(const IR::U1& value) { + Inst(Opcode::A32OrQFlag, value); } -IR::Value IREmitter::GetGEFlags() { - return Inst(Opcode::A32GetGEFlags, {}); +IR::U32 IREmitter::GetGEFlags() { + return Inst(Opcode::A32GetGEFlags); } -void IREmitter::SetGEFlags(const IR::Value& value) { - Inst(Opcode::A32SetGEFlags, {value}); +void IREmitter::SetGEFlags(const IR::U32& value) { + Inst(Opcode::A32SetGEFlags, value); } -void IREmitter::SetGEFlagsCompressed(const IR::Value& value) { - Inst(Opcode::A32SetGEFlagsCompressed, {value}); +void IREmitter::SetGEFlagsCompressed(const IR::U32& value) { + Inst(Opcode::A32SetGEFlagsCompressed, value); } -IR::Value IREmitter::GetFpscr() { - return Inst(Opcode::A32GetFpscr, {}); +IR::U32 IREmitter::GetFpscr() { + return Inst(Opcode::A32GetFpscr); } -void IREmitter::SetFpscr(const IR::Value& new_fpscr) { - Inst(Opcode::A32SetFpscr, {new_fpscr}); +void IREmitter::SetFpscr(const IR::U32& new_fpscr) { + Inst(Opcode::A32SetFpscr, new_fpscr); } -IR::Value IREmitter::GetFpscrNZCV() { - return Inst(Opcode::A32GetFpscrNZCV, {}); +IR::U32 IREmitter::GetFpscrNZCV() { + return Inst(Opcode::A32GetFpscrNZCV); } -void IREmitter::SetFpscrNZCV(const IR::Value& new_fpscr_nzcv) { - Inst(Opcode::A32SetFpscrNZCV, {new_fpscr_nzcv}); +void IREmitter::SetFpscrNZCV(const IR::U32& new_fpscr_nzcv) { + Inst(Opcode::A32SetFpscrNZCV, new_fpscr_nzcv); } void IREmitter::ClearExclusive() { - Inst(Opcode::A32ClearExclusive, {}); + Inst(Opcode::A32ClearExclusive); } -void IREmitter::SetExclusive(const IR::Value& vaddr, size_t byte_size) { +void IREmitter::SetExclusive(const IR::U32& vaddr, size_t byte_size) { ASSERT(byte_size == 1 || byte_size == 2 || byte_size == 4 || byte_size == 8 || byte_size == 16); - Inst(Opcode::A32SetExclusive, {vaddr, Imm8(u8(byte_size))}); + Inst(Opcode::A32SetExclusive, vaddr, Imm8(u8(byte_size))); } -IR::Value IREmitter::ReadMemory8(const IR::Value& vaddr) { - return Inst(Opcode::A32ReadMemory8, {vaddr}); +IR::U8 IREmitter::ReadMemory8(const IR::U32& vaddr) { + return Inst(Opcode::A32ReadMemory8, vaddr); } -IR::Value IREmitter::ReadMemory16(const IR::Value& vaddr) { - auto value = Inst(Opcode::A32ReadMemory16, {vaddr}); +IR::U16 IREmitter::ReadMemory16(const IR::U32& vaddr) { + auto value = Inst(Opcode::A32ReadMemory16, vaddr); return current_location.EFlag() ? ByteReverseHalf(value) : value; } -IR::Value IREmitter::ReadMemory32(const IR::Value& vaddr) { - auto value = Inst(Opcode::A32ReadMemory32, {vaddr}); +IR::U32 IREmitter::ReadMemory32(const IR::U32& vaddr) { + auto value = Inst(Opcode::A32ReadMemory32, vaddr); return current_location.EFlag() ? ByteReverseWord(value) : value; } -IR::Value IREmitter::ReadMemory64(const IR::Value& vaddr) { - auto value = Inst(Opcode::A32ReadMemory64, {vaddr}); +IR::U64 IREmitter::ReadMemory64(const IR::U32& vaddr) { + auto value = Inst(Opcode::A32ReadMemory64, vaddr); return current_location.EFlag() ? ByteReverseDual(value) : value; } -void IREmitter::WriteMemory8(const IR::Value& vaddr, const IR::Value& value) { - Inst(Opcode::A32WriteMemory8, {vaddr, value}); +void IREmitter::WriteMemory8(const IR::U32& vaddr, const IR::U8& value) { + Inst(Opcode::A32WriteMemory8, vaddr, value); } -void IREmitter::WriteMemory16(const IR::Value& vaddr, const IR::Value& value) { +void IREmitter::WriteMemory16(const IR::U32& vaddr, const IR::U16& value) { if (current_location.EFlag()) { auto v = ByteReverseHalf(value); - Inst(Opcode::A32WriteMemory16, {vaddr, v}); + Inst(Opcode::A32WriteMemory16, vaddr, v); } else { - Inst(Opcode::A32WriteMemory16, {vaddr, value}); + Inst(Opcode::A32WriteMemory16, vaddr, value); } } -void IREmitter::WriteMemory32(const IR::Value& vaddr, const IR::Value& value) { +void IREmitter::WriteMemory32(const IR::U32& vaddr, const IR::U32& value) { if (current_location.EFlag()) { auto v = ByteReverseWord(value); - Inst(Opcode::A32WriteMemory32, {vaddr, v}); + Inst(Opcode::A32WriteMemory32, vaddr, v); } else { - Inst(Opcode::A32WriteMemory32, {vaddr, value}); + Inst(Opcode::A32WriteMemory32, vaddr, value); } } -void IREmitter::WriteMemory64(const IR::Value& vaddr, const IR::Value& value) { +void IREmitter::WriteMemory64(const IR::U32& vaddr, const IR::U64& value) { if (current_location.EFlag()) { auto v = ByteReverseDual(value); - Inst(Opcode::A32WriteMemory64, {vaddr, v}); + Inst(Opcode::A32WriteMemory64, vaddr, v); } else { - Inst(Opcode::A32WriteMemory64, {vaddr, value}); + Inst(Opcode::A32WriteMemory64, vaddr, value); } } -IR::Value IREmitter::ExclusiveWriteMemory8(const IR::Value& vaddr, const IR::Value& value) { - return Inst(Opcode::A32ExclusiveWriteMemory8, {vaddr, value}); +IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value) { + return Inst(Opcode::A32ExclusiveWriteMemory8, vaddr, value); } -IR::Value IREmitter::ExclusiveWriteMemory16(const IR::Value& vaddr, const IR::Value& value) { +IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value) { if (current_location.EFlag()) { auto v = ByteReverseHalf(value); - return Inst(Opcode::A32ExclusiveWriteMemory16, {vaddr, v}); + return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, v); } else { - return Inst(Opcode::A32ExclusiveWriteMemory16, {vaddr, value}); + return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, value); } } -IR::Value IREmitter::ExclusiveWriteMemory32(const IR::Value& vaddr, const IR::Value& value) { +IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value) { if (current_location.EFlag()) { auto v = ByteReverseWord(value); - return Inst(Opcode::A32ExclusiveWriteMemory32, {vaddr, v}); + return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, v); } else { - return Inst(Opcode::A32ExclusiveWriteMemory32, {vaddr, value}); + return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, value); } } -IR::Value IREmitter::ExclusiveWriteMemory64(const IR::Value& vaddr, const IR::Value& value_lo, const IR::Value& value_hi) { +IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi) { if (current_location.EFlag()) { auto vlo = ByteReverseWord(value_lo); auto vhi = ByteReverseWord(value_hi); - return Inst(Opcode::A32ExclusiveWriteMemory64, {vaddr, vlo, vhi}); + return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, vlo, vhi); } else { - return Inst(Opcode::A32ExclusiveWriteMemory64, {vaddr, value_lo, value_hi}); + return Inst(Opcode::A32ExclusiveWriteMemory64, 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) { +void IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, CoprocReg CRd, CoprocReg CRn, CoprocReg CRm, size_t opc2) { ASSERT(coproc_no <= 15); std::array coproc_info{static_cast(coproc_no), static_cast(two ? 1 : 0), @@ -255,10 +255,10 @@ void IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, static_cast(CRn), static_cast(CRm), static_cast(opc2)}; - Inst(Opcode::A32CoprocInternalOperation, {IR::Value(coproc_info)}); + Inst(Opcode::A32CoprocInternalOperation, 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) { +void IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2, const IR::U32& word) { ASSERT(coproc_no <= 15); std::array coproc_info{static_cast(coproc_no), static_cast(two ? 1 : 0), @@ -266,19 +266,19 @@ void IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, A32:: static_cast(CRn), static_cast(CRm), static_cast(opc2)}; - Inst(Opcode::A32CoprocSendOneWord, {IR::Value(coproc_info), word}); + Inst(Opcode::A32CoprocSendOneWord, 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) { +void IREmitter::CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm, const IR::U32& word1, const IR::U32& 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::A32CoprocSendTwoWords, {IR::Value(coproc_info), word1, word2}); + Inst(Opcode::A32CoprocSendTwoWords, 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) { +IR::U32 IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2) { ASSERT(coproc_no <= 15); std::array coproc_info{static_cast(coproc_no), static_cast(two ? 1 : 0), @@ -286,19 +286,19 @@ IR::Value IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, A static_cast(CRn), static_cast(CRm), static_cast(opc2)}; - return Inst(Opcode::A32CoprocGetOneWord, {IR::Value(coproc_info)}); + return Inst(Opcode::A32CoprocGetOneWord, IR::Value(coproc_info)); } -IR::Value IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, A32::CoprocReg CRm) { +IR::U64 IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, 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::A32CoprocGetTwoWords, {IR::Value(coproc_info)}); + return Inst(Opcode::A32CoprocGetTwoWords, 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) { +void IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option) { ASSERT(coproc_no <= 15); std::array coproc_info{static_cast(coproc_no), static_cast(two ? 1 : 0), @@ -306,10 +306,10 @@ void IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, static_cast(CRd), static_cast(has_option ? 1 : 0), static_cast(option)}; - Inst(Opcode::A32CoprocLoadWords, {IR::Value(coproc_info), address}); + Inst(Opcode::A32CoprocLoadWords, 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) { +void IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option) { ASSERT(coproc_no <= 15); std::array coproc_info{static_cast(coproc_no), static_cast(two ? 1 : 0), @@ -317,7 +317,7 @@ void IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, static_cast(CRd), static_cast(has_option ? 1 : 0), static_cast(option)}; - Inst(Opcode::A32CoprocStoreWords, {IR::Value(coproc_info), address}); + Inst(Opcode::A32CoprocStoreWords, IR::Value(coproc_info), address); } } // namespace IR diff --git a/src/frontend/A32/ir_emitter.h b/src/frontend/A32/ir_emitter.h index be48cb07..b8272867 100644 --- a/src/frontend/A32/ir_emitter.h +++ b/src/frontend/A32/ir_emitter.h @@ -26,65 +26,65 @@ namespace A32 { */ class IREmitter : public IR::IREmitter { public: - explicit IREmitter(A32::LocationDescriptor descriptor) : IR::IREmitter(descriptor), current_location(descriptor) {} + explicit IREmitter(LocationDescriptor descriptor) : IR::IREmitter(descriptor), current_location(descriptor) {} - A32::LocationDescriptor current_location; + 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); + IR::U32 GetRegister(Reg source_reg); + IR::F32F64 GetExtendedRegister(ExtReg source_reg); + void SetRegister(const Reg dest_reg, const IR::U32& value); + void SetExtendedRegister(const ExtReg dest_reg, const IR::F32F64& 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 ALUWritePC(const IR::U32& value); + void BranchWritePC(const IR::U32& value); + void BXWritePC(const IR::U32& value); + void LoadWritePC(const IR::U32& value); + void CallSupervisor(const IR::U32& value); - 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::U32 GetCpsr(); + void SetCpsr(const IR::U32& value); + void SetCpsrNZCV(const IR::U32& value); + void SetCpsrNZCVQ(const IR::U32& value); + IR::U1 GetCFlag(); + void SetNFlag(const IR::U1& value); + void SetZFlag(const IR::U1& value); + void SetCFlag(const IR::U1& value); + void SetVFlag(const IR::U1& value); + void OrQFlag(const IR::U1& value); + IR::U32 GetGEFlags(); + void SetGEFlags(const IR::U32& value); + void SetGEFlagsCompressed(const IR::U32& value); - IR::Value GetFpscr(); - void SetFpscr(const IR::Value& new_fpscr); - IR::Value GetFpscrNZCV(); - void SetFpscrNZCV(const IR::Value& new_fpscr_nzcv); + IR::U32 GetFpscr(); + void SetFpscr(const IR::U32& new_fpscr); + IR::U32 GetFpscrNZCV(); + void SetFpscrNZCV(const IR::U32& 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 SetExclusive(const IR::U32& vaddr, size_t byte_size); + IR::U8 ReadMemory8(const IR::U32& vaddr); + IR::U16 ReadMemory16(const IR::U32& vaddr); + IR::U32 ReadMemory32(const IR::U32& vaddr); + IR::U64 ReadMemory64(const IR::U32& vaddr); + void WriteMemory8(const IR::U32& vaddr, const IR::U8& value); + void WriteMemory16(const IR::U32& vaddr, const IR::U16& value); + void WriteMemory32(const IR::U32& vaddr, const IR::U32& value); + void WriteMemory64(const IR::U32& vaddr, const IR::U64& value); + IR::U32 ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value); + IR::U32 ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value); + IR::U32 ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value); + IR::U32 ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& 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); + void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, CoprocReg CRd, CoprocReg CRn, CoprocReg CRm, size_t opc2); + void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2, const IR::U32& word); + void CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm, const IR::U32& word1, const IR::U32& word2); + IR::U32 CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2); + IR::U64 CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm); + void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option); + void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option); }; } // namespace IR diff --git a/src/frontend/A32/translate/translate_arm.cpp b/src/frontend/A32/translate/translate_arm.cpp index 40c268bd..29405876 100644 --- a/src/frontend/A32/translate/translate_arm.cpp +++ b/src/frontend/A32/translate/translate_arm.cpp @@ -121,7 +121,7 @@ bool ArmTranslatorVisitor::UnpredictableInstruction() { return false; } -A32::IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in) { +IR::ResultAndCarry ArmTranslatorVisitor::EmitImmShift(IR::U32 value, ShiftType type, Imm5 imm5, IR::U1 carry_in) { switch (type) { case ShiftType::LSL: return ir.LogicalShiftLeft(value, ir.Imm8(imm5), carry_in); @@ -141,7 +141,7 @@ A32::IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitImmShift(IR::Value valu return {}; } -A32::IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in) { +IR::ResultAndCarry ArmTranslatorVisitor::EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 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 e714425a..5447049e 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(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) { +static IR::U32 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 c3a22aa6..4604a1d1 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(A32::IREmitter& ir, bool P, bool U, bool W, Reg n, IR::Value offset) { +static IR::U32 GetAddress(A32::IREmitter& ir, bool P, bool U, bool W, Reg n, IR::U32 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(A32::IREmitter& 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::U32 start_address, IR::U32 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(A32::IREmitter& 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::U32 start_address, IR::U32 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/multiply.cpp b/src/frontend/A32/translate/translate_arm/multiply.cpp index 34e34e63..90c1e027 100644 --- a/src/frontend/A32/translate/translate_arm/multiply.cpp +++ b/src/frontend/A32/translate/translate_arm/multiply.cpp @@ -211,8 +211,7 @@ bool ArmTranslatorVisitor::arm_SMLAWy(Cond cond, Reg d, Reg a, Reg m, bool M, Re auto m32 = ir.GetRegister(m); if (M) m32 = ir.LogicalShiftRight(m32, ir.Imm8(16), ir.Imm1(0)).result; - auto m16 = ir.LeastSignificantHalf(m32); - m16 = ir.SignExtendWordToLong(ir.SignExtendHalfToWord(m16)); + auto m16 = ir.SignExtendWordToLong(ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32))); auto product = ir.LeastSignificantWord(ir.LogicalShiftRight64(ir.Mul64(n32, m16), ir.Imm8(16))); auto result_overflow = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); ir.SetRegister(d, result_overflow.result); @@ -229,8 +228,7 @@ bool ArmTranslatorVisitor::arm_SMULWy(Cond cond, Reg d, Reg m, bool M, Reg n) { auto m32 = ir.GetRegister(m); if (M) m32 = ir.LogicalShiftRight(m32, ir.Imm8(16), ir.Imm1(0)).result; - auto m16 = ir.LeastSignificantHalf(m32); - m16 = ir.SignExtendWordToLong(ir.SignExtendHalfToWord(m16)); + auto m16 = ir.SignExtendWordToLong(ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32))); auto result = ir.LogicalShiftRight64(ir.Mul64(n32, m16), ir.Imm8(16)); ir.SetRegister(d, ir.LeastSignificantWord(result)); } diff --git a/src/frontend/A32/translate/translate_arm/saturated.cpp b/src/frontend/A32/translate/translate_arm/saturated.cpp index 36fad32c..455d3175 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(A32::IREmitter& ir, IR::Value lo, IR::Value hi) { +static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) { return ir.Or(ir.And(lo, ir.Imm32(0xFFFF)), ir.LogicalShiftLeft(hi, ir.Imm8(16), ir.Imm1(0)).result); } -static IR::Value MostSignificantHalf(A32::IREmitter& ir, IR::Value value) { +static IR::U16 MostSignificantHalf(A32::IREmitter& ir, IR::U32 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 4c220e2c..03d9e2c7 100644 --- a/src/frontend/A32/translate/translate_arm/translate_arm.h +++ b/src/frontend/A32/translate/translate_arm/translate_arm.h @@ -49,10 +49,10 @@ struct ArmTranslatorVisitor final { struct ImmAndCarry { u32 imm32; - IR::Value carry; + IR::U1 carry; }; - ImmAndCarry ArmExpandImm_C(int rotate, u32 imm8, IR::Value carry_in) { + ImmAndCarry ArmExpandImm_C(int rotate, u32 imm8, IR::U1 carry_in) { u32 imm32 = imm8; auto carry_out = carry_in; if (rotate) { @@ -62,8 +62,8 @@ struct ArmTranslatorVisitor final { return {imm32, carry_out}; } - 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); + IR::ResultAndCarry EmitImmShift(IR::U32 value, ShiftType type, Imm5 imm5, IR::U1 carry_in); + IR::ResultAndCarry EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 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_arm/vfp2.cpp b/src/frontend/A32/translate/translate_arm/vfp2.cpp index 334b3e3a..a56239da 100644 --- a/src/frontend/A32/translate/translate_arm/vfp2.cpp +++ b/src/frontend/A32/translate/translate_arm/vfp2.cpp @@ -9,6 +9,9 @@ namespace Dynarmic { namespace A32 { +using F32 = IR::F32; +using F64 = IR::F64; + static ExtReg ToExtReg(bool sz, size_t base, bool bit) { if (sz) { return static_cast(static_cast(ExtReg::D0) + base + (bit ? 16 : 0)); @@ -99,10 +102,13 @@ bool ArmTranslatorVisitor::vfp2_VADD(Cond cond, bool D, size_t Vn, size_t Vd, bo return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPAdd64(reg_n, reg_m, true) - : ir.FPAdd32(reg_n, reg_m, true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPAdd64(reg_n, reg_m, true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPAdd32(reg_n, reg_m, true); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -117,10 +123,13 @@ bool ArmTranslatorVisitor::vfp2_VSUB(Cond cond, bool D, size_t Vn, size_t Vd, bo return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPSub64(reg_n, reg_m, true) - : ir.FPSub32(reg_n, reg_m, true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPSub64(reg_n, reg_m, true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPSub32(reg_n, reg_m, true); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -135,10 +144,13 @@ bool ArmTranslatorVisitor::vfp2_VMUL(Cond cond, bool D, size_t Vn, size_t Vd, bo return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPMul64(reg_n, reg_m, true) - : ir.FPMul32(reg_n, reg_m, true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPMul64(reg_n, reg_m, true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPMul32(reg_n, reg_m, true); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -154,10 +166,13 @@ bool ArmTranslatorVisitor::vfp2_VMLA(Cond cond, bool D, size_t Vn, size_t Vd, bo auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); auto reg_d = ir.GetExtendedRegister(d); - auto result = sz - ? ir.FPAdd64(reg_d, ir.FPMul64(reg_n, reg_m, true), true) - : ir.FPAdd32(reg_d, ir.FPMul32(reg_n, reg_m, true), true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPAdd64(reg_d, ir.FPMul64(reg_n, reg_m, true), true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPAdd32(reg_d, ir.FPMul32(reg_n, reg_m, true), true); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -173,10 +188,13 @@ bool ArmTranslatorVisitor::vfp2_VMLS(Cond cond, bool D, size_t Vn, size_t Vd, bo auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); auto reg_d = ir.GetExtendedRegister(d); - auto result = sz - ? ir.FPAdd64(reg_d, ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true)), true) - : ir.FPAdd32(reg_d, ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true)), true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPAdd64(reg_d, ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true)), true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPAdd32(reg_d, ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true)), true); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -191,10 +209,13 @@ bool ArmTranslatorVisitor::vfp2_VNMUL(Cond cond, bool D, size_t Vn, size_t Vd, b return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true)) - : ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true)); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true)); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true)); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -210,10 +231,13 @@ bool ArmTranslatorVisitor::vfp2_VNMLA(Cond cond, bool D, size_t Vn, size_t Vd, b auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); auto reg_d = ir.GetExtendedRegister(d); - auto result = sz - ? ir.FPAdd64(ir.FPNeg64(reg_d), ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true)), true) - : ir.FPAdd32(ir.FPNeg32(reg_d), ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true)), true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPAdd64(ir.FPNeg64(reg_d), ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true)), true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPAdd32(ir.FPNeg32(reg_d), ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true)), true); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -229,10 +253,13 @@ bool ArmTranslatorVisitor::vfp2_VNMLS(Cond cond, bool D, size_t Vn, size_t Vd, b auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); auto reg_d = ir.GetExtendedRegister(d); - auto result = sz - ? ir.FPAdd64(ir.FPNeg64(reg_d), ir.FPMul64(reg_n, reg_m, true), true) - : ir.FPAdd32(ir.FPNeg32(reg_d), ir.FPMul32(reg_n, reg_m, true), true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPAdd64(ir.FPNeg64(reg_d), ir.FPMul64(reg_n, reg_m, true), true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPAdd32(ir.FPNeg32(reg_d), ir.FPMul32(reg_n, reg_m, true), true); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -247,10 +274,13 @@ bool ArmTranslatorVisitor::vfp2_VDIV(Cond cond, bool D, size_t Vn, size_t Vd, bo return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { auto reg_n = ir.GetExtendedRegister(n); auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPDiv64(reg_n, reg_m, true) - : ir.FPDiv32(reg_n, reg_m, true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPDiv64(reg_n, reg_m, true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPDiv32(reg_n, reg_m, true); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -379,10 +409,13 @@ bool ArmTranslatorVisitor::vfp2_VABS(Cond cond, bool D, size_t Vd, bool sz, bool if (ConditionPassed(cond)) { return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) { auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPAbs64(reg_m) - : ir.FPAbs32(reg_m); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPAbs64(reg_m); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPAbs32(reg_m); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -395,10 +428,13 @@ bool ArmTranslatorVisitor::vfp2_VNEG(Cond cond, bool D, size_t Vd, bool sz, bool if (ConditionPassed(cond)) { return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) { auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPNeg64(reg_m) - : ir.FPNeg32(reg_m); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPNeg64(reg_m); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPNeg32(reg_m); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -411,10 +447,13 @@ bool ArmTranslatorVisitor::vfp2_VSQRT(Cond cond, bool D, size_t Vd, bool sz, boo if (ConditionPassed(cond)) { return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) { auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPSqrt64(reg_m) - : ir.FPSqrt32(reg_m); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPSqrt64(reg_m); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPSqrt32(reg_m); + ir.SetExtendedRegister(d, result); + } }); } return true; @@ -427,10 +466,13 @@ bool ArmTranslatorVisitor::vfp2_VCVT_f_to_f(Cond cond, bool D, size_t Vd, bool s // VCVT.F32.F64
if (ConditionPassed(cond)) { auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? ir.FPDoubleToSingle(reg_m, true) - : ir.FPSingleToDouble(reg_m, true); - ir.SetExtendedRegister(d, result); + if (sz) { + auto result = ir.FPDoubleToSingle(reg_m, true); + ir.SetExtendedRegister(d, result); + } else { + auto result = ir.FPSingleToDouble(reg_m, true); + ir.SetExtendedRegister(d, result); + } } return true; } @@ -443,14 +485,17 @@ bool ArmTranslatorVisitor::vfp2_VCVT_to_float(Cond cond, bool D, size_t Vd, bool // VCVT.F64.{S32,U32} , if (ConditionPassed(cond)) { auto reg_m = ir.GetExtendedRegister(m); - auto result = sz - ? is_signed + if (sz) { + auto result = is_signed ? ir.FPS32ToDouble(reg_m, round_to_nearest, true) - : ir.FPU32ToDouble(reg_m, round_to_nearest, true) - : is_signed + : ir.FPU32ToDouble(reg_m, round_to_nearest, true); + ir.SetExtendedRegister(d, result); + } else { + auto result = is_signed ? ir.FPS32ToSingle(reg_m, round_to_nearest, true) : ir.FPU32ToSingle(reg_m, round_to_nearest, true); - ir.SetExtendedRegister(d, result); + ir.SetExtendedRegister(d, result); + } } return true; } @@ -510,12 +555,11 @@ bool ArmTranslatorVisitor::vfp2_VCMP_zero(Cond cond, bool D, size_t Vd, bool sz, // VCMP{E}.F64
, #0.0 if (ConditionPassed(cond)) { auto reg_d = ir.GetExtendedRegister(d); - auto zero = sz - ? ir.TransferToFP64(ir.Imm64(0)) - : ir.TransferToFP32(ir.Imm32(0)); if (sz) { + auto zero = ir.TransferToFP64(ir.Imm64(0)); ir.FPCompare64(reg_d, zero, exc_on_qnan, true); } else { + auto zero = ir.TransferToFP32(ir.Imm32(0)); ir.FPCompare32(reg_d, zero, exc_on_qnan, true); } } diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 7921f940..c34daeb0 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -15,527 +15,522 @@ void IREmitter::Unimplemented() { } -Value IREmitter::Imm1(bool imm1) { - return Value(imm1); +U1 IREmitter::Imm1(bool imm1) { + return U1(Value(imm1)); } -Value IREmitter::Imm8(u8 imm8) { - return Value(imm8); +U8 IREmitter::Imm8(u8 imm8) { + return U8(Value(imm8)); } -Value IREmitter::Imm32(u32 imm32) { - return Value(imm32); +U32 IREmitter::Imm32(u32 imm32) { + return U32(Value(imm32)); } -Value IREmitter::Imm64(u64 imm64) { - return Value(imm64); +U64 IREmitter::Imm64(u64 imm64) { + return U64(Value(imm64)); } void IREmitter::PushRSB(const LocationDescriptor& return_location) { - Inst(Opcode::PushRSB, {IR::Value(return_location.Value())}); + Inst(Opcode::PushRSB, IR::Value(return_location.Value())); } -Value IREmitter::Pack2x32To1x64(const Value& lo, const Value& hi) { - return Inst(Opcode::Pack2x32To1x64, {lo, hi}); +U64 IREmitter::Pack2x32To1x64(const U32& lo, const U32& hi) { + return Inst(Opcode::Pack2x32To1x64, lo, hi); } -Value IREmitter::LeastSignificantWord(const Value& value) { - return Inst(Opcode::LeastSignificantWord, {value}); +U32 IREmitter::LeastSignificantWord(const U64& value) { + return Inst(Opcode::LeastSignificantWord, value); } -IREmitter::ResultAndCarry IREmitter::MostSignificantWord(const Value& value) { - auto result = Inst(Opcode::MostSignificantWord, {value}); - auto carry_out = Inst(Opcode::GetCarryFromOp, {result}); +ResultAndCarry IREmitter::MostSignificantWord(const U64& value) { + auto result = Inst(Opcode::MostSignificantWord, value); + auto carry_out = Inst(Opcode::GetCarryFromOp, result); return {result, carry_out}; } -Value IREmitter::LeastSignificantHalf(const Value& value) { - return Inst(Opcode::LeastSignificantHalf, {value}); +U16 IREmitter::LeastSignificantHalf(const U32& value) { + return Inst(Opcode::LeastSignificantHalf, value); } -Value IREmitter::LeastSignificantByte(const Value& value) { - return Inst(Opcode::LeastSignificantByte, {value}); +U8 IREmitter::LeastSignificantByte(const U32& value) { + return Inst(Opcode::LeastSignificantByte, value); } -Value IREmitter::MostSignificantBit(const Value& value) { - return Inst(Opcode::MostSignificantBit, {value}); +U1 IREmitter::MostSignificantBit(const U32& value) { + return Inst(Opcode::MostSignificantBit, value); } -Value IREmitter::IsZero(const Value& value) { - return Inst(Opcode::IsZero, {value}); +U1 IREmitter::IsZero(const U32& value) { + return Inst(Opcode::IsZero, value); } -Value IREmitter::IsZero64(const Value& value) { - return Inst(Opcode::IsZero64, {value}); +U1 IREmitter::IsZero64(const U64& value) { + return Inst(Opcode::IsZero64, value); } -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}); +ResultAndCarry IREmitter::LogicalShiftLeft(const U32& value_in, const U8& shift_amount, const U1& carry_in) { + auto result = Inst(Opcode::LogicalShiftLeft, value_in, shift_amount, carry_in); + auto carry_out = Inst(Opcode::GetCarryFromOp, result); return {result, carry_out}; } -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}); +ResultAndCarry IREmitter::LogicalShiftRight(const U32& value_in, const U8& shift_amount, const U1& 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 IREmitter::LogicalShiftRight64(const Value& value_in, const Value& shift_amount) { - return Inst(Opcode::LogicalShiftRight64, {value_in, shift_amount}); +U64 IREmitter::LogicalShiftRight64(const U64& value_in, const U8& shift_amount) { + return Inst(Opcode::LogicalShiftRight64, value_in, shift_amount); } -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}); +ResultAndCarry IREmitter::ArithmeticShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { + auto result = Inst(Opcode::ArithmeticShiftRight, value_in, shift_amount, carry_in); + auto carry_out = Inst(Opcode::GetCarryFromOp, result); return {result, carry_out}; } -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}); +ResultAndCarry IREmitter::RotateRight(const U32& value_in, const U8& shift_amount, const U1& carry_in) { + auto result = Inst(Opcode::RotateRight, value_in, shift_amount, carry_in); + auto carry_out = Inst(Opcode::GetCarryFromOp, result); return {result, carry_out}; } -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}); +ResultAndCarry IREmitter::RotateRightExtended(const U32& value_in, const U1& carry_in) { + auto result = Inst(Opcode::RotateRightExtended, value_in, carry_in); + auto carry_out = Inst(Opcode::GetCarryFromOp, result); return {result, carry_out}; } -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}); +ResultAndCarryAndOverflow IREmitter::AddWithCarry(const Value& a, const Value& b, const U1& 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 IREmitter::Add(const Value& a, const Value& b) { - return Inst(Opcode::AddWithCarry, {a, b, Imm1(0)}); +U32 IREmitter::Add(const U32& a, const U32& b) { + return Inst(Opcode::AddWithCarry, a, b, Imm1(0)); } -Value IREmitter::Add64(const Value& a, const Value& b) { - return Inst(Opcode::Add64, {a, b}); +U64 IREmitter::Add64(const U64& a, const U64& b) { + return Inst(Opcode::Add64, a, b); } -IREmitter::ResultAndCarryAndOverflow IREmitter::SubWithCarry(const Value& a, const Value& b, const Value& carry_in) { +ResultAndCarryAndOverflow IREmitter::SubWithCarry(const U32& a, const U32& b, const U1& 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}); - auto overflow = Inst(Opcode::GetOverflowFromOp, {result}); + auto result = Inst(Opcode::SubWithCarry, a, b, carry_in); + auto carry_out = Inst(Opcode::GetCarryFromOp, result); + auto overflow = Inst(Opcode::GetOverflowFromOp, result); return {result, carry_out, overflow}; } -Value IREmitter::Sub(const Value& a, const Value& b) { - return Inst(Opcode::SubWithCarry, {a, b, Imm1(1)}); +U32 IREmitter::Sub(const U32& a, const U32& b) { + return Inst(Opcode::SubWithCarry, a, b, Imm1(1)); } -Value IREmitter::Sub64(const Value& a, const Value& b) { - return Inst(Opcode::Sub64, {a, b}); +U64 IREmitter::Sub64(const U64& a, const U64& b) { + return Inst(Opcode::Sub64, a, b); } -Value IREmitter::Mul(const Value& a, const Value& b) { - return Inst(Opcode::Mul, {a, b}); +U32 IREmitter::Mul(const U32& a, const U32& b) { + return Inst(Opcode::Mul, a, b); } -Value IREmitter::Mul64(const Value& a, const Value& b) { - return Inst(Opcode::Mul64, {a, b}); +U64 IREmitter::Mul64(const U64& a, const U64& b) { + return Inst(Opcode::Mul64, a, b); } -Value IREmitter::And(const Value& a, const Value& b) { - return Inst(Opcode::And, {a, b}); +U32 IREmitter::And(const U32& a, const U32& b) { + return Inst(Opcode::And, a, b); } -Value IREmitter::Eor(const Value& a, const Value& b) { - return Inst(Opcode::Eor, {a, b}); +U32 IREmitter::Eor(const U32& a, const U32& b) { + return Inst(Opcode::Eor, a, b); } -Value IREmitter::Or(const Value& a, const Value& b) { - return Inst(Opcode::Or, {a, b}); +U32 IREmitter::Or(const U32& a, const U32& b) { + return Inst(Opcode::Or, a, b); } -Value IREmitter::Not(const Value& a) { - return Inst(Opcode::Not, {a}); +U32 IREmitter::Not(const U32& a) { + return Inst(Opcode::Not, a); } -Value IREmitter::SignExtendWordToLong(const Value& a) { - return Inst(Opcode::SignExtendWordToLong, {a}); +U64 IREmitter::SignExtendWordToLong(const U32& a) { + return Inst(Opcode::SignExtendWordToLong, a); } -Value IREmitter::SignExtendHalfToWord(const Value& a) { - return Inst(Opcode::SignExtendHalfToWord, {a}); +U32 IREmitter::SignExtendHalfToWord(const U16& a) { + return Inst(Opcode::SignExtendHalfToWord, a); } -Value IREmitter::SignExtendByteToWord(const Value& a) { - return Inst(Opcode::SignExtendByteToWord, {a}); +U32 IREmitter::SignExtendByteToWord(const U8& a) { + return Inst(Opcode::SignExtendByteToWord, a); } -Value IREmitter::ZeroExtendWordToLong(const Value& a) { - return Inst(Opcode::ZeroExtendWordToLong, {a}); +U64 IREmitter::ZeroExtendWordToLong(const U32& a) { + return Inst(Opcode::ZeroExtendWordToLong, a); } -Value IREmitter::ZeroExtendHalfToWord(const Value& a) { - return Inst(Opcode::ZeroExtendHalfToWord, {a}); +U32 IREmitter::ZeroExtendHalfToWord(const U16& a) { + return Inst(Opcode::ZeroExtendHalfToWord, a); } -Value IREmitter::ZeroExtendByteToWord(const Value& a) { - return Inst(Opcode::ZeroExtendByteToWord, {a}); +U32 IREmitter::ZeroExtendByteToWord(const U8& a) { + return Inst(Opcode::ZeroExtendByteToWord, a); } -Value IREmitter::ByteReverseWord(const Value& a) { - return Inst(Opcode::ByteReverseWord, {a}); +U32 IREmitter::ByteReverseWord(const U32& a) { + return Inst(Opcode::ByteReverseWord, a); } -Value IREmitter::ByteReverseHalf(const Value& a) { - return Inst(Opcode::ByteReverseHalf, {a}); +U16 IREmitter::ByteReverseHalf(const U16& a) { + return Inst(Opcode::ByteReverseHalf, a); } -Value IREmitter::ByteReverseDual(const Value& a) { - return Inst(Opcode::ByteReverseDual, {a}); +U64 IREmitter::ByteReverseDual(const U64& a) { + return Inst(Opcode::ByteReverseDual, a); } -Value IREmitter::CountLeadingZeros(const Value& a) { - return Inst(Opcode::CountLeadingZeros, {a}); +U32 IREmitter::CountLeadingZeros(const U32& a) { + return Inst(Opcode::CountLeadingZeros, a); } -IREmitter::ResultAndOverflow IREmitter::SignedSaturatedAdd(const Value& a, const Value& b) { - auto result = Inst(Opcode::SignedSaturatedAdd, {a, b}); - auto overflow = Inst(Opcode::GetOverflowFromOp, {result}); +ResultAndOverflow IREmitter::SignedSaturatedAdd(const U32& a, const U32& b) { + auto result = Inst(Opcode::SignedSaturatedAdd, a, b); + auto overflow = Inst(Opcode::GetOverflowFromOp, result); return {result, overflow}; } -IREmitter::ResultAndOverflow IREmitter::SignedSaturatedSub(const Value& a, const Value& b) { - auto result = Inst(Opcode::SignedSaturatedSub, {a, b}); - auto overflow = Inst(Opcode::GetOverflowFromOp, {result}); +ResultAndOverflow IREmitter::SignedSaturatedSub(const U32& a, const U32& b) { + auto result = Inst(Opcode::SignedSaturatedSub, a, b); + auto overflow = Inst(Opcode::GetOverflowFromOp, result); return {result, overflow}; } -IREmitter::ResultAndOverflow IREmitter::UnsignedSaturation(const Value& a, size_t bit_size_to_saturate_to) { +ResultAndOverflow IREmitter::UnsignedSaturation(const U32& 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}); + auto result = Inst(Opcode::UnsignedSaturation, a, Imm8(static_cast(bit_size_to_saturate_to))); + auto overflow = Inst(Opcode::GetOverflowFromOp, result); return {result, overflow}; } -IREmitter::ResultAndOverflow IREmitter::SignedSaturation(const Value& a, size_t bit_size_to_saturate_to) { +ResultAndOverflow IREmitter::SignedSaturation(const U32& 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}); + auto result = Inst(Opcode::SignedSaturation, a, Imm8(static_cast(bit_size_to_saturate_to))); + auto overflow = Inst(Opcode::GetOverflowFromOp, result); return {result, overflow}; } -IREmitter::ResultAndGE IREmitter::PackedAddU8(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedAddU8, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedAddU8(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedAddU8, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedAddS8(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedAddS8, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedAddS8(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedAddS8, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedAddU16(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedAddU16, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedAddU16(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedAddU16, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedAddS16(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedAddS16, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedAddS16(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedAddS16, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedSubU8(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedSubU8, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedSubU8(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedSubU8, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedSubS8(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedSubS8, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedSubS8(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedSubS8, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedSubU16(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedSubU16, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedSubU16(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedSubU16, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedSubS16(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedSubS16, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedSubS16(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedSubS16, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedAddSubU16(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedAddSubU16, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedAddSubU16(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedAddSubU16, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedAddSubS16(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedAddSubS16, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedAddSubS16(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedAddSubS16, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedSubAddU16(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedSubAddU16, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedSubAddU16(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedSubAddU16, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -IREmitter::ResultAndGE IREmitter::PackedSubAddS16(const Value& a, const Value& b) { - auto result = Inst(Opcode::PackedSubAddS16, {a, b}); - auto ge = Inst(Opcode::GetGEFromOp, {result}); +ResultAndGE IREmitter::PackedSubAddS16(const U32& a, const U32& b) { + auto result = Inst(Opcode::PackedSubAddS16, a, b); + auto ge = Inst(Opcode::GetGEFromOp, result); return {result, ge}; } -Value IREmitter::PackedHalvingAddU8(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingAddU8, {a, b}); +U32 IREmitter::PackedHalvingAddU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddU8, a, b); } -Value IREmitter::PackedHalvingAddS8(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingAddS8, {a, b}); +U32 IREmitter::PackedHalvingAddS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddS8, a, b); } -Value IREmitter::PackedHalvingSubU8(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingSubU8, {a, b}); +U32 IREmitter::PackedHalvingSubU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubU8, a, b); } -Value IREmitter::PackedHalvingSubS8(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingSubS8, {a, b}); +U32 IREmitter::PackedHalvingSubS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubS8, a, b); } -Value IREmitter::PackedHalvingAddU16(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingAddU16, {a, b}); +U32 IREmitter::PackedHalvingAddU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddU16, a, b); } -Value IREmitter::PackedHalvingAddS16(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingAddS16, {a, b}); +U32 IREmitter::PackedHalvingAddS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddS16, a, b); } -Value IREmitter::PackedHalvingSubU16(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingSubU16, {a, b}); +U32 IREmitter::PackedHalvingSubU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubU16, a, b); } -Value IREmitter::PackedHalvingSubS16(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingSubS16, {a, b}); +U32 IREmitter::PackedHalvingSubS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubS16, a, b); } -Value IREmitter::PackedHalvingAddSubU16(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingAddSubU16, {a, b}); +U32 IREmitter::PackedHalvingAddSubU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddSubU16, a, b); } -Value IREmitter::PackedHalvingAddSubS16(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingAddSubS16, {a, b}); +U32 IREmitter::PackedHalvingAddSubS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingAddSubS16, a, b); } -Value IREmitter::PackedHalvingSubAddU16(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingSubAddU16, {a, b}); +U32 IREmitter::PackedHalvingSubAddU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubAddU16, a, b); } -Value IREmitter::PackedHalvingSubAddS16(const Value& a, const Value& b) { - return Inst(Opcode::PackedHalvingSubAddS16, {a, b}); +U32 IREmitter::PackedHalvingSubAddS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedHalvingSubAddS16, a, b); } -Value IREmitter::PackedSaturatedAddU8(const Value& a, const Value& b) { - return Inst(Opcode::PackedSaturatedAddU8, {a, b}); +U32 IREmitter::PackedSaturatedAddU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedAddU8, a, b); } -Value IREmitter::PackedSaturatedAddS8(const Value& a, const Value& b) { - return Inst(Opcode::PackedSaturatedAddS8, {a, b}); +U32 IREmitter::PackedSaturatedAddS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedAddS8, a, b); } -Value IREmitter::PackedSaturatedSubU8(const Value& a, const Value& b) { - return Inst(Opcode::PackedSaturatedSubU8, {a, b}); +U32 IREmitter::PackedSaturatedSubU8(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedSubU8, a, b); } -Value IREmitter::PackedSaturatedSubS8(const Value& a, const Value& b) { - return Inst(Opcode::PackedSaturatedSubS8, {a, b}); +U32 IREmitter::PackedSaturatedSubS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedSubS8, a, b); } -Value IREmitter::PackedSaturatedAddU16(const Value& a, const Value& b) { - return Inst(Opcode::PackedSaturatedAddU16, {a, b}); +U32 IREmitter::PackedSaturatedAddU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedAddU16, a, b); } -Value IREmitter::PackedSaturatedAddS16(const Value& a, const Value& b) { - return Inst(Opcode::PackedSaturatedAddS16, {a, b}); +U32 IREmitter::PackedSaturatedAddS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedAddS16, a, b); } -Value IREmitter::PackedSaturatedSubU16(const Value& a, const Value& b) { - return Inst(Opcode::PackedSaturatedSubU16, {a, b}); +U32 IREmitter::PackedSaturatedSubU16(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedSubU16, a, b); } -Value IREmitter::PackedSaturatedSubS16(const Value& a, const Value& b) { - return Inst(Opcode::PackedSaturatedSubS16, {a, b}); +U32 IREmitter::PackedSaturatedSubS16(const U32& a, const U32& b) { + return Inst(Opcode::PackedSaturatedSubS16, a, b); } -Value IREmitter::PackedAbsDiffSumS8(const Value& a, const Value& b) { - return Inst(Opcode::PackedAbsDiffSumS8, {a, b}); +U32 IREmitter::PackedAbsDiffSumS8(const U32& a, const U32& b) { + return Inst(Opcode::PackedAbsDiffSumS8, a, b); } -Value IREmitter::PackedSelect(const Value& ge, const Value& a, const Value& b) { - return Inst(Opcode::PackedSelect, {ge, a, b}); +U32 IREmitter::PackedSelect(const U32& ge, const U32& a, const U32& b) { + return Inst(Opcode::PackedSelect, ge, a, b); } -Value IREmitter::TransferToFP32(const Value& a) { - return Inst(Opcode::TransferToFP32, {a}); +F32 IREmitter::TransferToFP32(const U32& a) { + return Inst(Opcode::TransferToFP32, a); } -Value IREmitter::TransferToFP64(const Value& a) { - return Inst(Opcode::TransferToFP64, {a}); +F64 IREmitter::TransferToFP64(const U64& a) { + return Inst(Opcode::TransferToFP64, a); } -Value IREmitter::TransferFromFP32(const Value& a) { - return Inst(Opcode::TransferFromFP32, {a}); +U32 IREmitter::TransferFromFP32(const F32& a) { + return Inst(Opcode::TransferFromFP32, a); } -Value IREmitter::TransferFromFP64(const Value& a) { - return Inst(Opcode::TransferFromFP64, {a}); +U64 IREmitter::TransferFromFP64(const F64& a) { + return Inst(Opcode::TransferFromFP64, a); } -Value IREmitter::FPAbs32(const Value& a) { - return Inst(Opcode::FPAbs32, {a}); +F32 IREmitter::FPAbs32(const F32& a) { + return Inst(Opcode::FPAbs32, a); } -Value IREmitter::FPAbs64(const Value& a) { - return Inst(Opcode::FPAbs64, {a}); +F64 IREmitter::FPAbs64(const F64& a) { + return Inst(Opcode::FPAbs64, a); } -Value IREmitter::FPAdd32(const Value& a, const Value& b, bool fpscr_controlled) { +F32 IREmitter::FPAdd32(const F32& a, const F32& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPAdd32, {a, b}); + return Inst(Opcode::FPAdd32, a, b); } -Value IREmitter::FPAdd64(const Value& a, const Value& b, bool fpscr_controlled) { +F64 IREmitter::FPAdd64(const F64& a, const F64& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPAdd64, {a, b}); + return Inst(Opcode::FPAdd64, a, b); } -void IREmitter::FPCompare32(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) { +void IREmitter::FPCompare32(const F32& a, const F32& b, bool exc_on_qnan, bool fpscr_controlled) { ASSERT(fpscr_controlled); - Inst(Opcode::FPCompare32, {a, b, Imm1(exc_on_qnan)}); + Inst(Opcode::FPCompare32, a, b, Imm1(exc_on_qnan)); } -void IREmitter::FPCompare64(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled) { +void IREmitter::FPCompare64(const F64& a, const F64& b, bool exc_on_qnan, bool fpscr_controlled) { ASSERT(fpscr_controlled); - Inst(Opcode::FPCompare64, {a, b, Imm1(exc_on_qnan)}); + Inst(Opcode::FPCompare64, a, b, Imm1(exc_on_qnan)); } -Value IREmitter::FPDiv32(const Value& a, const Value& b, bool fpscr_controlled) { +F32 IREmitter::FPDiv32(const F32& a, const F32& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPDiv32, {a, b}); + return Inst(Opcode::FPDiv32, a, b); } -Value IREmitter::FPDiv64(const Value& a, const Value& b, bool fpscr_controlled) { +F64 IREmitter::FPDiv64(const F64& a, const F64& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPDiv64, {a, b}); + return Inst(Opcode::FPDiv64, a, b); } -Value IREmitter::FPMul32(const Value& a, const Value& b, bool fpscr_controlled) { +F32 IREmitter::FPMul32(const F32& a, const F32& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPMul32, {a, b}); + return Inst(Opcode::FPMul32, a, b); } -Value IREmitter::FPMul64(const Value& a, const Value& b, bool fpscr_controlled) { +F64 IREmitter::FPMul64(const F64& a, const F64& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPMul64, {a, b}); + return Inst(Opcode::FPMul64, a, b); } -Value IREmitter::FPNeg32(const Value& a) { - return Inst(Opcode::FPNeg32, {a}); +F32 IREmitter::FPNeg32(const F32& a) { + return Inst(Opcode::FPNeg32, a); } -Value IREmitter::FPNeg64(const Value& a) { - return Inst(Opcode::FPNeg64, {a}); +F64 IREmitter::FPNeg64(const F64& a) { + return Inst(Opcode::FPNeg64, a); } -Value IREmitter::FPSqrt32(const Value& a) { - return Inst(Opcode::FPSqrt32, {a}); +F32 IREmitter::FPSqrt32(const F32& a) { + return Inst(Opcode::FPSqrt32, a); } -Value IREmitter::FPSqrt64(const Value& a) { - return Inst(Opcode::FPSqrt64, {a}); +F64 IREmitter::FPSqrt64(const F64& a) { + return Inst(Opcode::FPSqrt64, a); } -Value IREmitter::FPSub32(const Value& a, const Value& b, bool fpscr_controlled) { +F32 IREmitter::FPSub32(const F32& a, const F32& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPSub32, {a, b}); + return Inst(Opcode::FPSub32, a, b); } -Value IREmitter::FPSub64(const Value& a, const Value& b, bool fpscr_controlled) { +F64 IREmitter::FPSub64(const F64& a, const F64& b, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPSub64, {a, b}); + return Inst(Opcode::FPSub64, a, b); } -Value IREmitter::FPDoubleToSingle(const Value& a, bool fpscr_controlled) { +F32 IREmitter::FPDoubleToSingle(const F64& a, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPDoubleToSingle, {a}); + return Inst(Opcode::FPDoubleToSingle, a); } -Value IREmitter::FPSingleToDouble(const Value& a, bool fpscr_controlled) { +F64 IREmitter::FPSingleToDouble(const F32& a, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPSingleToDouble, {a}); + return Inst(Opcode::FPSingleToDouble, a); } -Value IREmitter::FPSingleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { +F32 IREmitter::FPSingleToS32(const F32& a, bool round_towards_zero, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPSingleToS32, {a, Imm1(round_towards_zero)}); + return Inst(Opcode::FPSingleToS32, a, Imm1(round_towards_zero)); } -Value IREmitter::FPSingleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { +F32 IREmitter::FPSingleToU32(const F32& a, bool round_towards_zero, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPSingleToU32, {a, Imm1(round_towards_zero)}); + return Inst(Opcode::FPSingleToU32, a, Imm1(round_towards_zero)); } -Value IREmitter::FPDoubleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { +F32 IREmitter::FPDoubleToS32(const F32& a, bool round_towards_zero, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPDoubleToS32, {a, Imm1(round_towards_zero)}); + return Inst(Opcode::FPDoubleToS32, a, Imm1(round_towards_zero)); } -Value IREmitter::FPDoubleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled) { +F32 IREmitter::FPDoubleToU32(const F32& a, bool round_towards_zero, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPDoubleToU32, {a, Imm1(round_towards_zero)}); + return Inst(Opcode::FPDoubleToU32, a, Imm1(round_towards_zero)); } -Value IREmitter::FPS32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) { +F32 IREmitter::FPS32ToSingle(const F32& a, bool round_to_nearest, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPS32ToSingle, {a, Imm1(round_to_nearest)}); + return Inst(Opcode::FPS32ToSingle, a, Imm1(round_to_nearest)); } -Value IREmitter::FPU32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled) { +F32 IREmitter::FPU32ToSingle(const F32& a, bool round_to_nearest, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPU32ToSingle, {a, Imm1(round_to_nearest)}); + return Inst(Opcode::FPU32ToSingle, a, Imm1(round_to_nearest)); } -Value IREmitter::FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) { +F64 IREmitter::FPS32ToDouble(const F32& a, bool round_to_nearest, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPS32ToDouble, {a, Imm1(round_to_nearest)}); + return Inst(Opcode::FPS32ToDouble, a, Imm1(round_to_nearest)); } -Value IREmitter::FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled) { +F64 IREmitter::FPU32ToDouble(const F32& a, bool round_to_nearest, bool fpscr_controlled) { ASSERT(fpscr_controlled); - return Inst(Opcode::FPU32ToDouble, {a, Imm1(round_to_nearest)}); + return Inst(Opcode::FPU32ToDouble, a, Imm1(round_to_nearest)); } void IREmitter::Breakpoint() { - Inst(Opcode::Breakpoint, {}); + Inst(Opcode::Breakpoint); } void IREmitter::SetTerm(const Terminal& terminal) { block.SetTerminal(terminal); } -Value IREmitter::Inst(Opcode op, std::initializer_list args) { - block.AppendNewInst(op, args); - return Value(&block.back()); -} - } // namespace IR } // namespace Dynarmic diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index ae670086..e9505d8f 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -28,6 +28,31 @@ namespace IR { enum class Opcode; +template +struct ResultAndCarry { + T result; + U1 carry; +}; + +template +struct ResultAndOverflow { + T result; + U1 overflow; +}; + +template +struct ResultAndCarryAndOverflow { + T result; + U1 carry; + U1 overflow; +}; + +template +struct ResultAndGE { + T result; + U32 ge; +}; + /** * Convenience class to construct a basic block of the intermediate representation. * `block` is the resulting block. @@ -39,151 +64,134 @@ public: Block block; - struct ResultAndCarry { - Value result; - Value carry; - }; - - struct ResultAndOverflow { - Value result; - Value overflow; - }; - - struct ResultAndCarryAndOverflow { - Value result; - Value carry; - Value overflow; - }; - - struct ResultAndGE { - Value result; - Value ge; - }; - void Unimplemented(); - Value Imm1(bool value); - Value Imm8(u8 value); - Value Imm32(u32 value); - Value Imm64(u64 value); + U1 Imm1(bool value); + U8 Imm8(u8 value); + U32 Imm32(u32 value); + U64 Imm64(u64 value); void PushRSB(const LocationDescriptor& return_location); - Value Pack2x32To1x64(const Value& lo, const Value& hi); - Value LeastSignificantWord(const Value& value); - ResultAndCarry MostSignificantWord(const Value& value); - Value LeastSignificantHalf(const Value& value); - Value LeastSignificantByte(const Value& value); - Value MostSignificantBit(const Value& value); - Value IsZero(const Value& value); - Value IsZero64(const Value& value); + U64 Pack2x32To1x64(const U32& lo, const U32& hi); + U32 LeastSignificantWord(const U64& value); + ResultAndCarry MostSignificantWord(const U64& value); + U16 LeastSignificantHalf(const U32& value); + U8 LeastSignificantByte(const U32& value); + U1 MostSignificantBit(const U32& value); + U1 IsZero(const U32& value); + U1 IsZero64(const U64& value); - ResultAndCarry LogicalShiftLeft(const Value& value_in, const Value& shift_amount, const Value& carry_in); - ResultAndCarry LogicalShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in); - Value LogicalShiftRight64(const Value& value_in, const Value& shift_amount); - ResultAndCarry ArithmeticShiftRight(const Value& value_in, const Value& shift_amount, const Value& carry_in); - ResultAndCarry RotateRight(const Value& value_in, const Value& shift_amount, const Value& carry_in); - ResultAndCarry RotateRightExtended(const Value& value_in, const Value& carry_in); - ResultAndCarryAndOverflow AddWithCarry(const Value& a, const Value& b, const Value& carry_in); - Value Add(const Value& a, const Value& b); - Value Add64(const Value& a, const Value& b); - ResultAndCarryAndOverflow SubWithCarry(const Value& a, const Value& b, const Value& carry_in); - Value Sub(const Value& a, const Value& b); - Value Sub64(const Value& a, const Value& b); - Value Mul(const Value& a, const Value& b); - Value Mul64(const Value& a, const Value& b); - Value And(const Value& a, const Value& b); - Value Eor(const Value& a, const Value& b); - Value Or(const Value& a, const Value& b); - Value Not(const Value& a); - Value SignExtendWordToLong(const Value& a); - Value SignExtendHalfToWord(const Value& a); - Value SignExtendByteToWord(const Value& a); - Value ZeroExtendWordToLong(const Value& a); - Value ZeroExtendHalfToWord(const Value& a); - Value ZeroExtendByteToWord(const Value& a); - Value ByteReverseWord(const Value& a); - Value ByteReverseHalf(const Value& a); - Value ByteReverseDual(const Value& a); - Value CountLeadingZeros(const Value& a); + ResultAndCarry LogicalShiftLeft(const U32& value_in, const U8& shift_amount, const U1& carry_in); + ResultAndCarry LogicalShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in); + U64 LogicalShiftRight64(const U64& value_in, const U8& shift_amount); + ResultAndCarry ArithmeticShiftRight(const U32& value_in, const U8& shift_amount, const U1& carry_in); + ResultAndCarry RotateRight(const U32& value_in, const U8& shift_amount, const U1& carry_in); + ResultAndCarry RotateRightExtended(const U32& value_in, const U1& carry_in); + ResultAndCarryAndOverflow AddWithCarry(const Value& a, const Value& b, const U1& carry_in); + U32 Add(const U32& a, const U32& b); + U64 Add64(const U64& a, const U64& b); + ResultAndCarryAndOverflow SubWithCarry(const U32& a, const U32& b, const U1& carry_in); + U32 Sub(const U32& a, const U32& b); + U64 Sub64(const U64& a, const U64& b); + U32 Mul(const U32& a, const U32& b); + U64 Mul64(const U64& a, const U64& b); + U32 And(const U32& a, const U32& b); + U32 Eor(const U32& a, const U32& b); + U32 Or(const U32& a, const U32& b); + U32 Not(const U32& a); + U64 SignExtendWordToLong(const U32& a); + U32 SignExtendHalfToWord(const U16& a); + U32 SignExtendByteToWord(const U8& a); + U64 ZeroExtendWordToLong(const U32& a); + U32 ZeroExtendHalfToWord(const U16& a); + U32 ZeroExtendByteToWord(const U8& a); + U32 ByteReverseWord(const U32& a); + U16 ByteReverseHalf(const U16& a); + U64 ByteReverseDual(const U64& a); + U32 CountLeadingZeros(const U32& a); - ResultAndOverflow SignedSaturatedAdd(const Value& a, const Value& b); - ResultAndOverflow SignedSaturatedSub(const Value& a, const Value& b); - ResultAndOverflow UnsignedSaturation(const Value& a, size_t bit_size_to_saturate_to); - ResultAndOverflow SignedSaturation(const Value& a, size_t bit_size_to_saturate_to); + ResultAndOverflow SignedSaturatedAdd(const U32& a, const U32& b); + ResultAndOverflow SignedSaturatedSub(const U32& a, const U32& b); + ResultAndOverflow UnsignedSaturation(const U32& a, size_t bit_size_to_saturate_to); + ResultAndOverflow SignedSaturation(const U32& a, size_t bit_size_to_saturate_to); - ResultAndGE PackedAddU8(const Value& a, const Value& b); - ResultAndGE PackedAddS8(const Value& a, const Value& b); - ResultAndGE PackedAddU16(const Value& a, const Value& b); - ResultAndGE PackedAddS16(const Value& a, const Value& b); - ResultAndGE PackedSubU8(const Value& a, const Value& b); - ResultAndGE PackedSubS8(const Value& a, const Value& b); - ResultAndGE PackedSubU16(const Value& a, const Value& b); - ResultAndGE PackedSubS16(const Value& a, const Value& b); - ResultAndGE PackedAddSubU16(const Value& a, const Value& b); - ResultAndGE PackedAddSubS16(const Value& a, const Value& b); - ResultAndGE PackedSubAddU16(const Value& a, const Value& b); - ResultAndGE PackedSubAddS16(const Value& a, const Value& b); - Value PackedHalvingAddU8(const Value& a, const Value& b); - Value PackedHalvingAddS8(const Value& a, const Value& b); - Value PackedHalvingSubU8(const Value& a, const Value& b); - Value PackedHalvingSubS8(const Value& a, const Value& b); - Value PackedHalvingAddU16(const Value& a, const Value& b); - Value PackedHalvingAddS16(const Value& a, const Value& b); - Value PackedHalvingSubU16(const Value& a, const Value& b); - Value PackedHalvingSubS16(const Value& a, const Value& b); - Value PackedHalvingAddSubU16(const Value& a, const Value& b); - Value PackedHalvingAddSubS16(const Value& a, const Value& b); - Value PackedHalvingSubAddU16(const Value& a, const Value& b); - Value PackedHalvingSubAddS16(const Value& a, const Value& b); - Value PackedSaturatedAddU8(const Value& a, const Value& b); - Value PackedSaturatedAddS8(const Value& a, const Value& b); - Value PackedSaturatedSubU8(const Value& a, const Value& b); - Value PackedSaturatedSubS8(const Value& a, const Value& b); - Value PackedSaturatedAddU16(const Value& a, const Value& b); - Value PackedSaturatedAddS16(const Value& a, const Value& b); - Value PackedSaturatedSubU16(const Value& a, const Value& b); - Value PackedSaturatedSubS16(const Value& a, const Value& b); - Value PackedAbsDiffSumS8(const Value& a, const Value& b); - Value PackedSelect(const Value& ge, const Value& a, const Value& b); + ResultAndGE PackedAddU8(const U32& a, const U32& b); + ResultAndGE PackedAddS8(const U32& a, const U32& b); + ResultAndGE PackedAddU16(const U32& a, const U32& b); + ResultAndGE PackedAddS16(const U32& a, const U32& b); + ResultAndGE PackedSubU8(const U32& a, const U32& b); + ResultAndGE PackedSubS8(const U32& a, const U32& b); + ResultAndGE PackedSubU16(const U32& a, const U32& b); + ResultAndGE PackedSubS16(const U32& a, const U32& b); + ResultAndGE PackedAddSubU16(const U32& a, const U32& b); + ResultAndGE PackedAddSubS16(const U32& a, const U32& b); + ResultAndGE PackedSubAddU16(const U32& a, const U32& b); + ResultAndGE PackedSubAddS16(const U32& a, const U32& b); + U32 PackedHalvingAddU8(const U32& a, const U32& b); + U32 PackedHalvingAddS8(const U32& a, const U32& b); + U32 PackedHalvingSubU8(const U32& a, const U32& b); + U32 PackedHalvingSubS8(const U32& a, const U32& b); + U32 PackedHalvingAddU16(const U32& a, const U32& b); + U32 PackedHalvingAddS16(const U32& a, const U32& b); + U32 PackedHalvingSubU16(const U32& a, const U32& b); + U32 PackedHalvingSubS16(const U32& a, const U32& b); + U32 PackedHalvingAddSubU16(const U32& a, const U32& b); + U32 PackedHalvingAddSubS16(const U32& a, const U32& b); + U32 PackedHalvingSubAddU16(const U32& a, const U32& b); + U32 PackedHalvingSubAddS16(const U32& a, const U32& b); + U32 PackedSaturatedAddU8(const U32& a, const U32& b); + U32 PackedSaturatedAddS8(const U32& a, const U32& b); + U32 PackedSaturatedSubU8(const U32& a, const U32& b); + U32 PackedSaturatedSubS8(const U32& a, const U32& b); + U32 PackedSaturatedAddU16(const U32& a, const U32& b); + U32 PackedSaturatedAddS16(const U32& a, const U32& b); + U32 PackedSaturatedSubU16(const U32& a, const U32& b); + U32 PackedSaturatedSubS16(const U32& a, const U32& b); + U32 PackedAbsDiffSumS8(const U32& a, const U32& b); + U32 PackedSelect(const U32& ge, const U32& a, const U32& b); - Value TransferToFP32(const Value& a); - Value TransferToFP64(const Value& a); - Value TransferFromFP32(const Value& a); - Value TransferFromFP64(const Value& a); - Value FPAbs32(const Value& a); - Value FPAbs64(const Value& a); - Value FPAdd32(const Value& a, const Value& b, bool fpscr_controlled); - Value FPAdd64(const Value& a, const Value& b, bool fpscr_controlled); - void FPCompare32(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled); - void FPCompare64(const Value& a, const Value& b, bool exc_on_qnan, bool fpscr_controlled); - Value FPDiv32(const Value& a, const Value& b, bool fpscr_controlled); - Value FPDiv64(const Value& a, const Value& b, bool fpscr_controlled); - Value FPMul32(const Value& a, const Value& b, bool fpscr_controlled); - Value FPMul64(const Value& a, const Value& b, bool fpscr_controlled); - Value FPNeg32(const Value& a); - Value FPNeg64(const Value& a); - Value FPSqrt32(const Value& a); - Value FPSqrt64(const Value& a); - Value FPSub32(const Value& a, const Value& b, bool fpscr_controlled); - Value FPSub64(const Value& a, const Value& b, bool fpscr_controlled); - Value FPDoubleToSingle(const Value& a, bool fpscr_controlled); - Value FPSingleToDouble(const Value& a, bool fpscr_controlled); - Value FPSingleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled); - Value FPSingleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled); - Value FPDoubleToS32(const Value& a, bool round_towards_zero, bool fpscr_controlled); - Value FPDoubleToU32(const Value& a, bool round_towards_zero, bool fpscr_controlled); - Value FPS32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled); - Value FPU32ToSingle(const Value& a, bool round_to_nearest, bool fpscr_controlled); - Value FPS32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled); - Value FPU32ToDouble(const Value& a, bool round_to_nearest, bool fpscr_controlled); + F32 TransferToFP32(const U32& a); + F64 TransferToFP64(const U64& a); + U32 TransferFromFP32(const F32& a); + U64 TransferFromFP64(const F64& a); + F32 FPAbs32(const F32& a); + F64 FPAbs64(const F64& a); + F32 FPAdd32(const F32& a, const F32& b, bool fpscr_controlled); + F64 FPAdd64(const F64& a, const F64& b, bool fpscr_controlled); + void FPCompare32(const F32& a, const F32& b, bool exc_on_qnan, bool fpscr_controlled); + void FPCompare64(const F64& a, const F64& b, bool exc_on_qnan, bool fpscr_controlled); + F32 FPDiv32(const F32& a, const F32& b, bool fpscr_controlled); + F64 FPDiv64(const F64& a, const F64& b, bool fpscr_controlled); + F32 FPMul32(const F32& a, const F32& b, bool fpscr_controlled); + F64 FPMul64(const F64& a, const F64& b, bool fpscr_controlled); + F32 FPNeg32(const F32& a); + F64 FPNeg64(const F64& a); + F32 FPSqrt32(const F32& a); + F64 FPSqrt64(const F64& a); + F32 FPSub32(const F32& a, const F32& b, bool fpscr_controlled); + F64 FPSub64(const F64& a, const F64& b, bool fpscr_controlled); + F32 FPDoubleToSingle(const F64& a, bool fpscr_controlled); + F64 FPSingleToDouble(const F32& a, bool fpscr_controlled); + F32 FPSingleToS32(const F32& a, bool round_towards_zero, bool fpscr_controlled); + F32 FPSingleToU32(const F32& a, bool round_towards_zero, bool fpscr_controlled); + F32 FPDoubleToS32(const F32& a, bool round_towards_zero, bool fpscr_controlled); + F32 FPDoubleToU32(const F32& a, bool round_towards_zero, bool fpscr_controlled); + F32 FPS32ToSingle(const F32& a, bool round_to_nearest, bool fpscr_controlled); + F32 FPU32ToSingle(const F32& a, bool round_to_nearest, bool fpscr_controlled); + F64 FPS32ToDouble(const F32& a, bool round_to_nearest, bool fpscr_controlled); + F64 FPU32ToDouble(const F32& a, bool round_to_nearest, bool fpscr_controlled); void Breakpoint(); void SetTerm(const Terminal& terminal); protected: - Value Inst(Opcode op, std::initializer_list args); + template + T Inst(Opcode op, Args ...args) { + block.AppendNewInst(op, {Value(args)...}); + return T(Value(&block.back())); + } }; } // namespace IR diff --git a/src/frontend/ir/opcodes.h b/src/frontend/ir/opcodes.h index 05c20e12..467ea864 100644 --- a/src/frontend/ir/opcodes.h +++ b/src/frontend/ir/opcodes.h @@ -30,22 +30,30 @@ constexpr size_t OpcodeCount = static_cast(Opcode::NUM_OPCODE); * The intermediate representation is typed. These are the used by our IR. */ enum class Type { - Void, - A32Reg, - A32ExtReg, - A64Reg, - A64Vec, - Opaque, - U1, - U8, - U16, - U32, - U64, - F32, - F64, - CoprocInfo, + Void = 0, + A32Reg = 1 << 0, + A32ExtReg = 1 << 1, + A64Reg = 1 << 2, + A64Vec = 1 << 3, + Opaque = 1 << 4, + U1 = 1 << 5, + U8 = 1 << 6, + U16 = 1 << 7, + U32 = 1 << 8, + U64 = 1 << 9, + F32 = 1 << 10, + F64 = 1 << 11, + CoprocInfo = 1 << 12, }; +constexpr Type operator|(Type a, Type b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +constexpr Type operator&(Type a, Type b) { + return static_cast(static_cast(a) & static_cast(b)); +} + /// Get return type of an opcode Type GetTypeOf(Opcode op); diff --git a/src/frontend/ir/value.h b/src/frontend/ir/value.h index 033cc528..c101ca6e 100644 --- a/src/frontend/ir/value.h +++ b/src/frontend/ir/value.h @@ -6,6 +6,7 @@ #pragma once +#include "common/assert.h" #include "common/common_types.h" #include "frontend/A32/types.h" @@ -18,7 +19,7 @@ class Inst; * A representation of a value in the IR. * A value may either be an immediate or the result of a microinstruction. */ -class Value final { +class Value { public: Value() : type(Type::Void) {} explicit Value(Inst* value); @@ -62,5 +63,30 @@ private: }; static_assert(sizeof(Value) <= 2 * sizeof(u64), "IR::Value should be kept small in size"); +template +class TypedValue final : public Value { +public: + TypedValue() : Value() {} + + template + /* implicit */ TypedValue(const TypedValue& value) : Value(value) { + static_assert((other_type & type_) != Type::Void); + ASSERT((value.GetType() & type_) != Type::Void); + } + + explicit TypedValue(const Value& value) : Value(value) { + ASSERT((value.GetType() & type_) != Type::Void); + } +}; + +using U1 = TypedValue; +using U8 = TypedValue; +using U16 = TypedValue; +using U32 = TypedValue; +using U64 = TypedValue; +using F32 = TypedValue; +using F64 = TypedValue; +using F32F64 = TypedValue; + } // namespace IR } // namespace Dynarmic