diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da59d6f5..9fd65fe5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -175,6 +175,7 @@ add_library(dynarmic frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp frontend/A64/translate/impl/sys_dc.cpp frontend/A64/translate/impl/system.cpp + frontend/A64/translate/impl/system_flag_format.cpp frontend/A64/translate/impl/system_flag_manipulation.cpp frontend/A64/translate/translate.cpp frontend/A64/translate/translate.h diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 078e97db..d1d3fbf2 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -87,8 +87,8 @@ INST(RMIF, "RMIF", "10111 //INST(SETF16, "SETF16", "0011101000000000010010nnnnn01101") // ARMv8.4 // System - Flag format instructions -//INST(XAFlag, "XAFlag", "11010101000000000100000000111111") // ARMv8.5 -//INST(AXFlag, "AXFlag", "11010101000000000100000001011111") // ARMv8.5 +INST(XAFlag, "XAFlag", "11010101000000000100000000111111") // ARMv8.5 +INST(AXFlag, "AXFlag", "11010101000000000100000001011111") // ARMv8.5 // SYS: Data Cache INST(DC_IVAC, "DC IVAC", "110101010000100001110110001ttttt") diff --git a/src/frontend/A64/translate/impl/system_flag_format.cpp b/src/frontend/A64/translate/impl/system_flag_format.cpp new file mode 100644 index 00000000..c7fc56d9 --- /dev/null +++ b/src/frontend/A64/translate/impl/system_flag_format.cpp @@ -0,0 +1,47 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2019 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 "frontend/A64/translate/impl/impl.h" + +namespace Dynarmic::A64 { + +bool TranslatorVisitor::AXFlag() { + const IR::U32 nzcv = ir.GetNZCVRaw(); + + const IR::U32 z = ir.And(nzcv, ir.Imm32(0x40000000)); + const IR::U32 c = ir.And(nzcv, ir.Imm32(0x20000000)); + const IR::U32 v = ir.And(nzcv, ir.Imm32(0x10000000)); + + const IR::U32 new_z = ir.Or(ir.LogicalShiftLeft(v, ir.Imm8(2)), z); + const IR::U32 new_c = ir.And(ir.And(c, ir.Not(ir.LogicalShiftLeft(v, ir.Imm8(1)))), ir.Imm32(0x20000000)); + + ir.SetNZCVRaw(ir.Or(new_z, new_c)); + return true; +} + +bool TranslatorVisitor::XAFlag() { + const IR::U32 nzcv = ir.GetNZCVRaw(); + + const IR::U32 z = ir.And(nzcv, ir.Imm32(0x40000000)); + const IR::U32 c = ir.And(nzcv, ir.Imm32(0x20000000)); + + const IR::U32 not_z = ir.And(ir.Not(z), ir.Imm32(0x40000000)); + const IR::U32 not_c = ir.And(ir.Not(c), ir.Imm32(0x20000000)); + + const IR::U32 new_n = ir.And(ir.LogicalShiftLeft(not_c, ir.Imm8(2)), + ir.LogicalShiftLeft(not_z, ir.Imm8(1))); + const IR::U32 new_z = ir.And(z, ir.LogicalShiftLeft(c, ir.Imm8(1))); + const IR::U32 new_c = ir.Or(c, ir.LogicalShiftRight(z, ir.Imm8(1))); + const IR::U32 new_v = ir.And(ir.LogicalShiftRight(not_c, ir.Imm8(1)), + ir.LogicalShiftRight(z, ir.Imm8(2))); + + const IR::U32 result = ir.Or(ir.Or(ir.Or(new_n, new_z), new_c), new_v); + + ir.SetNZCVRaw(result); + return true; +} + +} // namespace Dynarmic::A64