8b3bc92bce
The guest program often accesses the NZCV flags directly much less often than we need to use them for jumps and other such uses. Therefore, we store our flags in cpsr_nzcv in a x64-friendly format. This allows for a reduction in conditional jump related code.
53 lines
1.6 KiB
C++
53 lines
1.6 KiB
C++
/* This file is part of the dynarmic project.
|
|
* Copyright (c) 2016 MerryMage
|
|
* SPDX-License-Identifier: 0BSD
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "common/common_types.h"
|
|
#include "common/bit_util.h"
|
|
|
|
namespace Dynarmic::Backend::X64::NZCV {
|
|
|
|
constexpr u32 arm_mask = 0xF000'0000;
|
|
constexpr u32 x64_mask = 0xC101;
|
|
|
|
constexpr size_t x64_n_flag_bit = 15;
|
|
constexpr size_t x64_z_flag_bit = 14;
|
|
constexpr size_t x64_c_flag_bit = 8;
|
|
constexpr size_t x64_v_flag_bit = 0;
|
|
|
|
/// This is a constant used to create the x64 flags format from the ARM format.
|
|
/// NZCV * multiplier: NZCV0NZCV000NZCV
|
|
/// x64_flags format: NZ-----C-------V
|
|
constexpr u32 to_x64_multiplier = 0x1081;
|
|
|
|
/// This is a constant used to create the ARM format from the x64 flags format.
|
|
constexpr u32 from_x64_multiplier = 0x1021'0000;
|
|
|
|
inline u32 ToX64(u32 nzcv) {
|
|
/* Naive implementation:
|
|
u32 x64_flags = 0;
|
|
x64_flags |= Common::Bit<31>(cpsr) ? 1 << 15 : 0;
|
|
x64_flags |= Common::Bit<30>(cpsr) ? 1 << 14 : 0;
|
|
x64_flags |= Common::Bit<29>(cpsr) ? 1 << 8 : 0;
|
|
x64_flags |= Common::Bit<28>(cpsr) ? 1 : 0;
|
|
return x64_flags;
|
|
*/
|
|
return ((nzcv >> 28) * to_x64_multiplier) & x64_mask;
|
|
}
|
|
|
|
inline u32 FromX64(u32 x64_flags) {
|
|
/* Naive implementation:
|
|
u32 nzcv = 0;
|
|
nzcv |= Common::Bit<15>(x64_flags) ? 1 << 31 : 0;
|
|
nzcv |= Common::Bit<14>(x64_flags) ? 1 << 30 : 0;
|
|
nzcv |= Common::Bit<8>(x64_flags) ? 1 << 29 : 0;
|
|
nzcv |= Common::Bit<0>(x64_flags) ? 1 << 28 : 0;
|
|
return nzcv;
|
|
*/
|
|
return ((x64_flags & x64_mask) * from_x64_multiplier) & arm_mask;
|
|
}
|
|
|
|
} // namespace Dynarmic::Backend::X64::NZCV
|