Interpreter: Make signedness and narrowing conversions explicit

Makes our conversions between the different signs explicit to indicate
that they're intentional and also silences compiler warnings when
compiling with sign conversion or stricter truncation warnings enabled.
This commit is contained in:
Lioncash 2021-08-18 07:21:30 -04:00
parent 33154de614
commit b7b45eb111
9 changed files with 235 additions and 219 deletions

View File

@ -111,9 +111,9 @@ void Interpreter::Shutdown()
{ {
} }
static int startTrace = 0; static bool s_start_trace = false;
static void Trace(UGeckoInstruction& inst) static void Trace(const UGeckoInstruction& inst)
{ {
std::string regs; std::string regs;
for (size_t i = 0; i < std::size(PowerPC::ppcState.gpr); i++) for (size_t i = 0; i < std::size(PowerPC::ppcState.gpr); i++)
@ -166,12 +166,12 @@ int Interpreter::SingleStepInner()
m_prev_inst.hex = PowerPC::Read_Opcode(PC); m_prev_inst.hex = PowerPC::Read_Opcode(PC);
// Uncomment to trace the interpreter // Uncomment to trace the interpreter
// if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624) // if ((PC & 0x00FFFFFF) >= 0x000AB54C && (PC & 0x00FFFFFF) <= 0x000AB624)
// startTrace = 1; // s_start_trace = true;
// else // else
// startTrace = 0; // s_start_trace = false;
if (startTrace) if (s_start_trace)
{ {
Trace(m_prev_inst); Trace(m_prev_inst);
} }
@ -186,7 +186,7 @@ int Interpreter::SingleStepInner()
else if (MSR.FP) else if (MSR.FP)
{ {
m_op_table[m_prev_inst.OPCD](m_prev_inst); m_op_table[m_prev_inst.OPCD](m_prev_inst);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
CheckExceptions(); CheckExceptions();
} }
@ -202,7 +202,7 @@ int Interpreter::SingleStepInner()
else else
{ {
m_op_table[m_prev_inst.OPCD](m_prev_inst); m_op_table[m_prev_inst.OPCD](m_prev_inst);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
CheckExceptions(); CheckExceptions();
} }
@ -234,7 +234,7 @@ void Interpreter::SingleStep()
CoreTiming::g.slice_length = 1; CoreTiming::g.slice_length = 1;
PowerPC::ppcState.downcount = 0; PowerPC::ppcState.downcount = 0;
if (PowerPC::ppcState.Exceptions) if (PowerPC::ppcState.Exceptions != 0)
{ {
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
PC = NPC; PC = NPC;
@ -243,10 +243,10 @@ void Interpreter::SingleStep()
//#define SHOW_HISTORY //#define SHOW_HISTORY
#ifdef SHOW_HISTORY #ifdef SHOW_HISTORY
std::vector<int> PCVec; static std::vector<u32> s_pc_vec;
std::vector<int> PCBlockVec; static std::vector<u32> s_pc_block_vec;
int ShowBlocks = 30; constexpr u32 s_show_blocks = 30;
int ShowSteps = 300; constexpr u32 s_show_steps = 300;
#endif #endif
// FastRun - inspired by GCemu (to imitate the JIT so that they can be compared). // FastRun - inspired by GCemu (to imitate the JIT so that they can be compared).
@ -263,9 +263,9 @@ void Interpreter::Run()
if (SConfig::GetInstance().bEnableDebugging) if (SConfig::GetInstance().bEnableDebugging)
{ {
#ifdef SHOW_HISTORY #ifdef SHOW_HISTORY
PCBlockVec.push_back(PC); s_pc_block_vec.push_back(PC);
if (PCBlockVec.size() > ShowBlocks) if (s_pc_block_vec.size() > s_show_blocks)
PCBlockVec.erase(PCBlockVec.begin()); s_pc_block_vec.erase(s_pc_block_vec.begin());
#endif #endif
// Debugging friendly version of inner loop. Tries to do the timing as similarly to the // Debugging friendly version of inner loop. Tries to do the timing as similarly to the
@ -277,9 +277,9 @@ void Interpreter::Run()
for (i = 0; !m_end_block; i++) for (i = 0; !m_end_block; i++)
{ {
#ifdef SHOW_HISTORY #ifdef SHOW_HISTORY
PCVec.push_back(PC); s_pc_vec.push_back(PC);
if (PCVec.size() > ShowSteps) if (s_pc_vec.size() > s_show_steps)
PCVec.erase(PCVec.begin()); s_pc_vec.erase(s_pc_vec.begin());
#endif #endif
// 2: check for breakpoint // 2: check for breakpoint
@ -288,20 +288,20 @@ void Interpreter::Run()
#ifdef SHOW_HISTORY #ifdef SHOW_HISTORY
NOTICE_LOG_FMT(POWERPC, "----------------------------"); NOTICE_LOG_FMT(POWERPC, "----------------------------");
NOTICE_LOG_FMT(POWERPC, "Blocks:"); NOTICE_LOG_FMT(POWERPC, "Blocks:");
for (const int entry : PCBlockVec) for (const u32 entry : s_pc_block_vec)
NOTICE_LOG_FMT(POWERPC, "PC: {:#010x}", entry); NOTICE_LOG_FMT(POWERPC, "PC: {:#010x}", entry);
NOTICE_LOG_FMT(POWERPC, "----------------------------"); NOTICE_LOG_FMT(POWERPC, "----------------------------");
NOTICE_LOG_FMT(POWERPC, "Steps:"); NOTICE_LOG_FMT(POWERPC, "Steps:");
for (size_t j = 0; j < PCVec.size(); j++) for (size_t j = 0; j < s_pc_vec.size(); j++)
{ {
// Write space // Write space
if (j > 0) if (j > 0)
{ {
if (PCVec[j] != PCVec[(j - 1) + 4] if (s_pc_vec[j] != s_pc_vec[(j - 1) + 4]
NOTICE_LOG_FMT(POWERPC, ""); NOTICE_LOG_FMT(POWERPC, "");
} }
NOTICE_LOG_FMT(POWERPC, "PC: {:#010x}", PCVec[j]); NOTICE_LOG_FMT(POWERPC, "PC: {:#010x}", s_pc_vec[j]);
} }
#endif #endif
INFO_LOG_FMT(POWERPC, "Hit Breakpoint - {:08x}", PC); INFO_LOG_FMT(POWERPC, "Hit Breakpoint - {:08x}", PC);

View File

@ -7,7 +7,6 @@
#include "Core/HLE/HLE.h" #include "Core/HLE/HLE.h"
#include "Core/PowerPC/Interpreter/ExceptionUtils.h" #include "Core/PowerPC/Interpreter/ExceptionUtils.h"
#include "Core/PowerPC/Interpreter/Interpreter.h" #include "Core/PowerPC/Interpreter/Interpreter.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
void Interpreter::bx(UGeckoInstruction inst) void Interpreter::bx(UGeckoInstruction inst)
@ -15,10 +14,12 @@ void Interpreter::bx(UGeckoInstruction inst)
if (inst.LK) if (inst.LK)
LR = PC + 4; LR = PC + 4;
const auto address = u32(SignExt26(inst.LI << 2));
if (inst.AA) if (inst.AA)
NPC = SignExt26(inst.LI << 2); NPC = address;
else else
NPC = PC + SignExt26(inst.LI << 2); NPC = PC + address;
m_end_block = true; m_end_block = true;
} }
@ -29,11 +30,11 @@ void Interpreter::bcx(UGeckoInstruction inst)
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
CTR--; CTR--;
const bool true_false = ((inst.BO >> 3) & 1); const bool true_false = ((inst.BO >> 3) & 1) != 0;
const bool only_counter_check = ((inst.BO >> 4) & 1); const bool only_counter_check = ((inst.BO >> 4) & 1) != 0;
const bool only_condition_check = ((inst.BO >> 2) & 1); const bool only_condition_check = ((inst.BO >> 2) & 1) != 0;
const u32 ctr_check = ((CTR != 0) ^ (inst.BO >> 1)) & 1; const u32 ctr_check = ((CTR != 0) ^ (inst.BO >> 1)) & 1;
const bool counter = only_condition_check || ctr_check; const bool counter = only_condition_check || ctr_check != 0;
const bool condition = const bool condition =
only_counter_check || (PowerPC::ppcState.cr.GetBit(inst.BI) == u32(true_false)); only_counter_check || (PowerPC::ppcState.cr.GetBit(inst.BI) == u32(true_false));
@ -42,10 +43,12 @@ void Interpreter::bcx(UGeckoInstruction inst)
if (inst.LK) if (inst.LK)
LR = PC + 4; LR = PC + 4;
const auto address = u32(SignExt16(s16(inst.BD << 2)));
if (inst.AA) if (inst.AA)
NPC = SignExt16(inst.BD << 2); NPC = address;
else else
NPC = PC + SignExt16(inst.BD << 2); NPC = PC + address;
} }
m_end_block = true; m_end_block = true;
@ -53,13 +56,13 @@ void Interpreter::bcx(UGeckoInstruction inst)
void Interpreter::bcctrx(UGeckoInstruction inst) void Interpreter::bcctrx(UGeckoInstruction inst)
{ {
DEBUG_ASSERT_MSG(POWERPC, inst.BO_2 & BO_DONT_DECREMENT_FLAG, DEBUG_ASSERT_MSG(POWERPC, (inst.BO_2 & BO_DONT_DECREMENT_FLAG) != 0,
"bcctrx with decrement and test CTR option is invalid!"); "bcctrx with decrement and test CTR option is invalid!");
const u32 condition = const u32 condition =
((inst.BO_2 >> 4) | (PowerPC::ppcState.cr.GetBit(inst.BI_2) == ((inst.BO_2 >> 3) & 1))) & 1; ((inst.BO_2 >> 4) | (PowerPC::ppcState.cr.GetBit(inst.BI_2) == ((inst.BO_2 >> 3) & 1))) & 1;
if (condition) if (condition != 0)
{ {
NPC = CTR & (~3); NPC = CTR & (~3);
if (inst.LK_3) if (inst.LK_3)
@ -78,7 +81,7 @@ void Interpreter::bclrx(UGeckoInstruction inst)
const u32 condition = const u32 condition =
((inst.BO_2 >> 4) | (PowerPC::ppcState.cr.GetBit(inst.BI_2) == ((inst.BO_2 >> 3) & 1))) & 1; ((inst.BO_2 >> 4) | (PowerPC::ppcState.cr.GetBit(inst.BI_2) == ((inst.BO_2 >> 3) & 1))) & 1;
if (counter & condition) if ((counter & condition) != 0)
{ {
NPC = LR & (~3); NPC = LR & (~3);
if (inst.LK_3) if (inst.LK_3)

View File

@ -312,37 +312,39 @@ inline FPResult NI_msub(UReg_FPSCR* fpscr, double a, double c, double b)
// used by stfsXX instructions and ps_rsqrte // used by stfsXX instructions and ps_rsqrte
inline u32 ConvertToSingle(u64 x) inline u32 ConvertToSingle(u64 x)
{ {
u32 exp = (x >> 52) & 0x7ff; const u32 exp = u32((x >> 52) & 0x7ff);
if (exp > 896 || (x & ~Common::DOUBLE_SIGN) == 0) if (exp > 896 || (x & ~Common::DOUBLE_SIGN) == 0)
{ {
return ((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff); return u32(((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff));
} }
else if (exp >= 874) else if (exp >= 874)
{ {
u32 t = (u32)(0x80000000 | ((x & Common::DOUBLE_FRAC) >> 21)); u32 t = u32(0x80000000 | ((x & Common::DOUBLE_FRAC) >> 21));
t = t >> (905 - exp); t = t >> (905 - exp);
t |= (x >> 32) & 0x80000000; t |= u32((x >> 32) & 0x80000000);
return t; return t;
} }
else else
{ {
// This is said to be undefined. // This is said to be undefined.
// The code is based on hardware tests. // The code is based on hardware tests.
return ((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff); return u32(((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff));
} }
} }
// used by psq_stXX operations. // used by psq_stXX operations.
inline u32 ConvertToSingleFTZ(u64 x) inline u32 ConvertToSingleFTZ(u64 x)
{ {
u32 exp = (x >> 52) & 0x7ff; const u32 exp = u32((x >> 52) & 0x7ff);
if (exp > 896 || (x & ~Common::DOUBLE_SIGN) == 0) if (exp > 896 || (x & ~Common::DOUBLE_SIGN) == 0)
{ {
return ((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff); return u32(((x >> 32) & 0xc0000000) | ((x >> 29) & 0x3fffffff));
} }
else else
{ {
return (x >> 32) & 0x80000000; return u32((x >> 32) & 0x80000000);
} }
} }

View File

@ -22,9 +22,9 @@ enum class RoundingMode
TowardsNegativeInfinity = 0b11 TowardsNegativeInfinity = 0b11
}; };
static void SetFI(UReg_FPSCR* fpscr, int FI) void SetFI(UReg_FPSCR* fpscr, u32 FI)
{ {
if (FI) if (FI != 0)
{ {
SetFPException(fpscr, FPSCR_XX); SetFPException(fpscr, FPSCR_XX);
} }
@ -484,7 +484,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
const auto compute_result = [inst](double value) { const auto compute_result = [inst](double value) {
const double result = Common::ApproximateReciprocal(value); const double result = Common::ApproximateReciprocal(value);
rPS(inst.FD).Fill(result); rPS(inst.FD).Fill(result);
PowerPC::UpdateFPRFSingle(result); PowerPC::UpdateFPRFSingle(float(result));
}; };
if (b == 0.0) if (b == 0.0)

View File

@ -10,10 +10,10 @@
void Interpreter::Helper_UpdateCR0(u32 value) void Interpreter::Helper_UpdateCR0(u32 value)
{ {
s64 sign_extended = (s64)(s32)value; const s64 sign_extended = s64{s32(value)};
u64 cr_val = (u64)sign_extended; u64 cr_val = u64(sign_extended);
cr_val = (cr_val & ~(1ull << PowerPC::CR_EMU_SO_BIT)) | cr_val = (cr_val & ~(1ULL << PowerPC::CR_EMU_SO_BIT)) |
((u64)PowerPC::GetXER_SO() << PowerPC::CR_EMU_SO_BIT); (u64{PowerPC::GetXER_SO()} << PowerPC::CR_EMU_SO_BIT);
PowerPC::ppcState.cr.fields[0] = cr_val; PowerPC::ppcState.cr.fields[0] = cr_val;
} }
@ -26,16 +26,16 @@ u32 Interpreter::Helper_Carry(u32 value1, u32 value2)
void Interpreter::addi(UGeckoInstruction inst) void Interpreter::addi(UGeckoInstruction inst)
{ {
if (inst.RA) if (inst.RA)
rGPR[inst.RD] = rGPR[inst.RA] + inst.SIMM_16; rGPR[inst.RD] = rGPR[inst.RA] + u32(inst.SIMM_16);
else else
rGPR[inst.RD] = inst.SIMM_16; rGPR[inst.RD] = u32(inst.SIMM_16);
} }
void Interpreter::addic(UGeckoInstruction inst) void Interpreter::addic(UGeckoInstruction inst)
{ {
u32 a = rGPR[inst.RA]; const u32 a = rGPR[inst.RA];
u32 imm = (u32)(s32)inst.SIMM_16; const u32 imm = u32(s32{inst.SIMM_16});
// TODO(ector): verify this thing
rGPR[inst.RD] = a + imm; rGPR[inst.RD] = a + imm;
PowerPC::SetCarry(Helper_Carry(a, imm)); PowerPC::SetCarry(Helper_Carry(a, imm));
} }
@ -49,9 +49,9 @@ void Interpreter::addic_rc(UGeckoInstruction inst)
void Interpreter::addis(UGeckoInstruction inst) void Interpreter::addis(UGeckoInstruction inst)
{ {
if (inst.RA) if (inst.RA)
rGPR[inst.RD] = rGPR[inst.RA] + (inst.SIMM_16 << 16); rGPR[inst.RD] = rGPR[inst.RA] + u32(inst.SIMM_16 << 16);
else else
rGPR[inst.RD] = (inst.SIMM_16 << 16); rGPR[inst.RD] = u32(inst.SIMM_16 << 16);
} }
void Interpreter::andi_rc(UGeckoInstruction inst) void Interpreter::andi_rc(UGeckoInstruction inst)
@ -62,7 +62,7 @@ void Interpreter::andi_rc(UGeckoInstruction inst)
void Interpreter::andis_rc(UGeckoInstruction inst) void Interpreter::andis_rc(UGeckoInstruction inst)
{ {
rGPR[inst.RA] = rGPR[inst.RS] & ((u32)inst.UIMM << 16); rGPR[inst.RA] = rGPR[inst.RS] & (u32{inst.UIMM} << 16);
Helper_UpdateCR0(rGPR[inst.RA]); Helper_UpdateCR0(rGPR[inst.RA]);
} }
@ -100,7 +100,7 @@ void Interpreter::cmpli(UGeckoInstruction inst)
void Interpreter::mulli(UGeckoInstruction inst) void Interpreter::mulli(UGeckoInstruction inst)
{ {
rGPR[inst.RD] = (s32)rGPR[inst.RA] * inst.SIMM_16; rGPR[inst.RD] = u32(s32(rGPR[inst.RA]) * inst.SIMM_16);
} }
void Interpreter::ori(UGeckoInstruction inst) void Interpreter::ori(UGeckoInstruction inst)
@ -110,26 +110,26 @@ void Interpreter::ori(UGeckoInstruction inst)
void Interpreter::oris(UGeckoInstruction inst) void Interpreter::oris(UGeckoInstruction inst)
{ {
rGPR[inst.RA] = rGPR[inst.RS] | (inst.UIMM << 16); rGPR[inst.RA] = rGPR[inst.RS] | (u32{inst.UIMM} << 16);
} }
void Interpreter::subfic(UGeckoInstruction inst) void Interpreter::subfic(UGeckoInstruction inst)
{ {
s32 immediate = inst.SIMM_16; const s32 immediate = inst.SIMM_16;
rGPR[inst.RD] = immediate - (int)rGPR[inst.RA]; rGPR[inst.RD] = u32(immediate - s32(rGPR[inst.RA]));
PowerPC::SetCarry((rGPR[inst.RA] == 0) || (Helper_Carry(0 - rGPR[inst.RA], immediate))); PowerPC::SetCarry((rGPR[inst.RA] == 0) || (Helper_Carry(0 - rGPR[inst.RA], u32(immediate))));
} }
void Interpreter::twi(UGeckoInstruction inst) void Interpreter::twi(UGeckoInstruction inst)
{ {
const s32 a = rGPR[inst.RA]; const s32 a = s32(rGPR[inst.RA]);
const s32 b = inst.SIMM_16; const s32 b = inst.SIMM_16;
const s32 TO = inst.TO; const u32 TO = inst.TO;
DEBUG_LOG_FMT(POWERPC, "twi rA {:x} SIMM {:x} TO {:x}", a, b, TO); DEBUG_LOG_FMT(POWERPC, "twi rA {:x} SIMM {:x} TO {:x}", a, b, TO);
if (((a < b) && (TO & 0x10)) || ((a > b) && (TO & 0x08)) || ((a == b) && (TO & 0x04)) || if ((a < b && (TO & 0x10) != 0) || (a > b && (TO & 0x08) != 0) || (a == b && (TO & 0x04) != 0) ||
(((u32)a < (u32)b) && (TO & 0x02)) || (((u32)a > (u32)b) && (TO & 0x01))) (u32(a) < u32(b) && (TO & 0x02) != 0) || (u32(a) > u32(b) && (TO & 0x01) != 0))
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM;
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
@ -144,7 +144,7 @@ void Interpreter::xori(UGeckoInstruction inst)
void Interpreter::xoris(UGeckoInstruction inst) void Interpreter::xoris(UGeckoInstruction inst)
{ {
rGPR[inst.RA] = rGPR[inst.RS] ^ (inst.UIMM << 16); rGPR[inst.RA] = rGPR[inst.RS] ^ (u32{inst.UIMM} << 16);
} }
void Interpreter::rlwimix(UGeckoInstruction inst) void Interpreter::rlwimix(UGeckoInstruction inst)
@ -206,7 +206,7 @@ void Interpreter::cmpl(UGeckoInstruction inst)
void Interpreter::cntlzwx(UGeckoInstruction inst) void Interpreter::cntlzwx(UGeckoInstruction inst)
{ {
rGPR[inst.RA] = Common::CountLeadingZeros(rGPR[inst.RS]); rGPR[inst.RA] = u32(Common::CountLeadingZeros(rGPR[inst.RS]));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RA]); Helper_UpdateCR0(rGPR[inst.RA]);
@ -222,7 +222,7 @@ void Interpreter::eqvx(UGeckoInstruction inst)
void Interpreter::extsbx(UGeckoInstruction inst) void Interpreter::extsbx(UGeckoInstruction inst)
{ {
rGPR[inst.RA] = (u32)(s32)(s8)rGPR[inst.RS]; rGPR[inst.RA] = u32(s32(s8(rGPR[inst.RS])));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RA]); Helper_UpdateCR0(rGPR[inst.RA]);
@ -230,18 +230,18 @@ void Interpreter::extsbx(UGeckoInstruction inst)
void Interpreter::extshx(UGeckoInstruction inst) void Interpreter::extshx(UGeckoInstruction inst)
{ {
rGPR[inst.RA] = (u32)(s32)(s16)rGPR[inst.RS]; rGPR[inst.RA] = u32(s32(s16(rGPR[inst.RS])));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RA]); Helper_UpdateCR0(rGPR[inst.RA]);
} }
void Interpreter::nandx(UGeckoInstruction _inst) void Interpreter::nandx(UGeckoInstruction inst)
{ {
rGPR[_inst.RA] = ~(rGPR[_inst.RS] & rGPR[_inst.RB]); rGPR[inst.RA] = ~(rGPR[inst.RS] & rGPR[inst.RB]);
if (_inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[_inst.RA]); Helper_UpdateCR0(rGPR[inst.RA]);
} }
void Interpreter::norx(UGeckoInstruction inst) void Interpreter::norx(UGeckoInstruction inst)
@ -270,8 +270,8 @@ void Interpreter::orcx(UGeckoInstruction inst)
void Interpreter::slwx(UGeckoInstruction inst) void Interpreter::slwx(UGeckoInstruction inst)
{ {
u32 amount = rGPR[inst.RB]; const u32 amount = rGPR[inst.RB];
rGPR[inst.RA] = (amount & 0x20) ? 0 : rGPR[inst.RS] << (amount & 0x1f); rGPR[inst.RA] = (amount & 0x20) != 0 ? 0 : rGPR[inst.RS] << (amount & 0x1f);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RA]); Helper_UpdateCR0(rGPR[inst.RA]);
@ -279,11 +279,11 @@ void Interpreter::slwx(UGeckoInstruction inst)
void Interpreter::srawx(UGeckoInstruction inst) void Interpreter::srawx(UGeckoInstruction inst)
{ {
int rb = rGPR[inst.RB]; const u32 rb = rGPR[inst.RB];
if (rb & 0x20) if ((rb & 0x20) != 0)
{ {
if (rGPR[inst.RS] & 0x80000000) if ((rGPR[inst.RS] & 0x80000000) != 0)
{ {
rGPR[inst.RA] = 0xFFFFFFFF; rGPR[inst.RA] = 0xFFFFFFFF;
PowerPC::SetCarry(1); PowerPC::SetCarry(1);
@ -296,9 +296,9 @@ void Interpreter::srawx(UGeckoInstruction inst)
} }
else else
{ {
int amount = rb & 0x1f; const u32 amount = rb & 0x1f;
s32 rrs = rGPR[inst.RS]; const s32 rrs = s32(rGPR[inst.RS]);
rGPR[inst.RA] = rrs >> amount; rGPR[inst.RA] = u32(rrs >> amount);
PowerPC::SetCarry(rrs < 0 && amount > 0 && (u32(rrs) << (32 - amount)) != 0); PowerPC::SetCarry(rrs < 0 && amount > 0 && (u32(rrs) << (32 - amount)) != 0);
} }
@ -309,11 +309,10 @@ void Interpreter::srawx(UGeckoInstruction inst)
void Interpreter::srawix(UGeckoInstruction inst) void Interpreter::srawix(UGeckoInstruction inst)
{ {
int amount = inst.SH; const u32 amount = inst.SH;
const s32 rrs = s32(rGPR[inst.RS]);
s32 rrs = rGPR[inst.RS];
rGPR[inst.RA] = rrs >> amount;
rGPR[inst.RA] = u32(rrs >> amount);
PowerPC::SetCarry(rrs < 0 && amount > 0 && (u32(rrs) << (32 - amount)) != 0); PowerPC::SetCarry(rrs < 0 && amount > 0 && (u32(rrs) << (32 - amount)) != 0);
if (inst.Rc) if (inst.Rc)
@ -322,8 +321,8 @@ void Interpreter::srawix(UGeckoInstruction inst)
void Interpreter::srwx(UGeckoInstruction inst) void Interpreter::srwx(UGeckoInstruction inst)
{ {
u32 amount = rGPR[inst.RB]; const u32 amount = rGPR[inst.RB];
rGPR[inst.RA] = (amount & 0x20) ? 0 : (rGPR[inst.RS] >> (amount & 0x1f)); rGPR[inst.RA] = (amount & 0x20) != 0 ? 0 : (rGPR[inst.RS] >> (amount & 0x1f));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR0(rGPR[inst.RA]); Helper_UpdateCR0(rGPR[inst.RA]);
@ -331,14 +330,14 @@ void Interpreter::srwx(UGeckoInstruction inst)
void Interpreter::tw(UGeckoInstruction inst) void Interpreter::tw(UGeckoInstruction inst)
{ {
const s32 a = rGPR[inst.RA]; const s32 a = s32(rGPR[inst.RA]);
const s32 b = rGPR[inst.RB]; const s32 b = s32(rGPR[inst.RB]);
const s32 TO = inst.TO; const u32 TO = inst.TO;
DEBUG_LOG_FMT(POWERPC, "tw rA {:x} rB {:x} TO {:x}", a, b, TO); DEBUG_LOG_FMT(POWERPC, "tw rA {:x} rB {:x} TO {:x}", a, b, TO);
if (((a < b) && (TO & 0x10)) || ((a > b) && (TO & 0x08)) || ((a == b) && (TO & 0x04)) || if ((a < b && (TO & 0x10) != 0) || (a > b && (TO & 0x08) != 0) || (a == b && (TO & 0x04) != 0) ||
(((u32)a < (u32)b) && (TO & 0x02)) || (((u32)a > (u32)b) && (TO & 0x01))) ((u32(a) < u32(b)) && (TO & 0x02) != 0) || ((u32(a) > u32(b)) && (TO & 0x01) != 0))
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM;
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
@ -444,8 +443,8 @@ void Interpreter::addzex(UGeckoInstruction inst)
void Interpreter::divwx(UGeckoInstruction inst) void Interpreter::divwx(UGeckoInstruction inst)
{ {
const s32 a = rGPR[inst.RA]; const auto a = s32(rGPR[inst.RA]);
const s32 b = rGPR[inst.RB]; const auto b = s32(rGPR[inst.RB]);
const bool overflow = b == 0 || (static_cast<u32>(a) == 0x80000000 && b == -1); const bool overflow = b == 0 || (static_cast<u32>(a) == 0x80000000 && b == -1);
if (overflow) if (overflow)

View File

@ -17,12 +17,12 @@
static u32 Helper_Get_EA(const PowerPC::PowerPCState& ppcs, const UGeckoInstruction inst) static u32 Helper_Get_EA(const PowerPC::PowerPCState& ppcs, const UGeckoInstruction inst)
{ {
return inst.RA ? (ppcs.gpr[inst.RA] + inst.SIMM_16) : (u32)inst.SIMM_16; return inst.RA ? (ppcs.gpr[inst.RA] + u32(inst.SIMM_16)) : u32(inst.SIMM_16);
} }
static u32 Helper_Get_EA_U(const PowerPC::PowerPCState& ppcs, const UGeckoInstruction inst) static u32 Helper_Get_EA_U(const PowerPC::PowerPCState& ppcs, const UGeckoInstruction inst)
{ {
return (ppcs.gpr[inst.RA] + inst.SIMM_16); return (ppcs.gpr[inst.RA] + u32(inst.SIMM_16));
} }
static u32 Helper_Get_EA_X(const PowerPC::PowerPCState& ppcs, const UGeckoInstruction inst) static u32 Helper_Get_EA_X(const PowerPC::PowerPCState& ppcs, const UGeckoInstruction inst)
@ -205,7 +205,7 @@ void Interpreter::lfsx(UGeckoInstruction inst)
void Interpreter::lha(UGeckoInstruction inst) void Interpreter::lha(UGeckoInstruction inst)
{ {
const u32 temp = (u32)(s32)(s16)PowerPC::Read_U16(Helper_Get_EA(PowerPC::ppcState, inst)); const u32 temp = u32(s32(s16(PowerPC::Read_U16(Helper_Get_EA(PowerPC::ppcState, inst)))));
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
{ {
@ -216,7 +216,7 @@ void Interpreter::lha(UGeckoInstruction inst)
void Interpreter::lhau(UGeckoInstruction inst) void Interpreter::lhau(UGeckoInstruction inst)
{ {
const u32 address = Helper_Get_EA_U(PowerPC::ppcState, inst); const u32 address = Helper_Get_EA_U(PowerPC::ppcState, inst);
const u32 temp = (u32)(s32)(s16)PowerPC::Read_U16(address); const u32 temp = u32(s32(s16(PowerPC::Read_U16(address))));
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
{ {
@ -258,11 +258,11 @@ void Interpreter::lmw(UGeckoInstruction inst)
return; return;
} }
for (int i = inst.RD; i <= 31; i++, address += 4) for (u32 i = inst.RD; i <= 31; i++, address += 4)
{ {
const u32 temp_reg = PowerPC::Read_U32(address); const u32 temp_reg = PowerPC::Read_U32(address);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
PanicAlertFmt("DSI exception in lmw"); PanicAlertFmt("DSI exception in lmw");
NOTICE_LOG_FMT(POWERPC, "DSI exception in lmw"); NOTICE_LOG_FMT(POWERPC, "DSI exception in lmw");
@ -286,10 +286,10 @@ void Interpreter::stmw(UGeckoInstruction inst)
return; return;
} }
for (int i = inst.RS; i <= 31; i++, address += 4) for (u32 i = inst.RS; i <= 31; i++, address += 4)
{ {
PowerPC::Write_U32(rGPR[i], address); PowerPC::Write_U32(rGPR[i], address);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
PanicAlertFmt("DSI exception in stmw"); PanicAlertFmt("DSI exception in stmw");
NOTICE_LOG_FMT(POWERPC, "DSI exception in stmw"); NOTICE_LOG_FMT(POWERPC, "DSI exception in stmw");
@ -536,13 +536,13 @@ void Interpreter::eciwx(UGeckoInstruction inst)
{ {
const u32 EA = Helper_Get_EA_X(PowerPC::ppcState, inst); const u32 EA = Helper_Get_EA_X(PowerPC::ppcState, inst);
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000)) if ((PowerPC::ppcState.spr[SPR_EAR] & 0x80000000) == 0)
{ {
GenerateDSIException(EA); GenerateDSIException(EA);
return; return;
} }
if (EA & 3) if ((EA & 0b11) != 0)
{ {
GenerateAlignmentException(EA); GenerateAlignmentException(EA);
return; return;
@ -555,13 +555,13 @@ void Interpreter::ecowx(UGeckoInstruction inst)
{ {
const u32 EA = Helper_Get_EA_X(PowerPC::ppcState, inst); const u32 EA = Helper_Get_EA_X(PowerPC::ppcState, inst);
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000)) if ((PowerPC::ppcState.spr[SPR_EAR] & 0x80000000) == 0)
{ {
GenerateDSIException(EA); GenerateDSIException(EA);
return; return;
} }
if (EA & 3) if ((EA & 0b11) != 0)
{ {
GenerateAlignmentException(EA); GenerateAlignmentException(EA);
return; return;
@ -610,22 +610,22 @@ void Interpreter::lbzx(UGeckoInstruction inst)
void Interpreter::lhaux(UGeckoInstruction inst) void Interpreter::lhaux(UGeckoInstruction inst)
{ {
const u32 address = Helper_Get_EA_UX(PowerPC::ppcState, inst); const u32 address = Helper_Get_EA_UX(PowerPC::ppcState, inst);
const s32 temp = (s32)(s16)PowerPC::Read_U16(address); const s32 temp = s32{s16(PowerPC::Read_U16(address))};
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
{ {
rGPR[inst.RD] = temp; rGPR[inst.RD] = u32(temp);
rGPR[inst.RA] = address; rGPR[inst.RA] = address;
} }
} }
void Interpreter::lhax(UGeckoInstruction inst) void Interpreter::lhax(UGeckoInstruction inst)
{ {
const s32 temp = (s32)(s16)PowerPC::Read_U16(Helper_Get_EA_X(PowerPC::ppcState, inst)); const s32 temp = s32{s16(PowerPC::Read_U16(Helper_Get_EA_X(PowerPC::ppcState, inst)))};
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
{ {
rGPR[inst.RD] = temp; rGPR[inst.RD] = u32(temp);
} }
} }
@ -675,15 +675,15 @@ void Interpreter::lswx(UGeckoInstruction inst)
// Confirmed by hardware test that the zero case doesn't zero rGPR[r] // Confirmed by hardware test that the zero case doesn't zero rGPR[r]
for (u32 n = 0; n < static_cast<u8>(PowerPC::ppcState.xer_stringctrl); n++) for (u32 n = 0; n < static_cast<u8>(PowerPC::ppcState.xer_stringctrl); n++)
{ {
const int reg = (inst.RD + (n >> 2)) & 0x1f; const u32 reg = (inst.RD + (n >> 2)) & 0x1f;
const int offset = (n & 3) << 3; const u32 offset = (n & 3) << 3;
if ((n & 3) == 0) if ((n & 0b11) == 0)
rGPR[reg] = 0; rGPR[reg] = 0;
const u32 temp_value = PowerPC::Read_U8(EA) << (24 - offset); const u32 temp_value = PowerPC::Read_U8(EA) << (24 - offset);
// Not64 (Homebrew N64 Emulator for Wii) triggers the following case. // Not64 (Homebrew N64 Emulator for Wii) triggers the following case.
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
NOTICE_LOG_FMT(POWERPC, "DSI exception in lswx"); NOTICE_LOG_FMT(POWERPC, "DSI exception in lswx");
return; return;
@ -842,10 +842,8 @@ void Interpreter::sthx(UGeckoInstruction inst)
// FIXME: Should rollback if a DSI occurs // FIXME: Should rollback if a DSI occurs
void Interpreter::lswi(UGeckoInstruction inst) void Interpreter::lswi(UGeckoInstruction inst)
{ {
u32 EA; u32 EA = 0;
if (inst.RA == 0) if (inst.RA != 0)
EA = 0;
else
EA = rGPR[inst.RA]; EA = rGPR[inst.RA];
if (MSR.LE) if (MSR.LE)
@ -854,14 +852,12 @@ void Interpreter::lswi(UGeckoInstruction inst)
return; return;
} }
u32 n; u32 n = 32;
if (inst.NB == 0) if (inst.NB != 0)
n = 32;
else
n = inst.NB; n = inst.NB;
int r = inst.RD - 1; u32 r = u32{inst.RD} - 1;
int i = 0; u32 i = 0;
while (n > 0) while (n > 0)
{ {
if (i == 0) if (i == 0)
@ -872,7 +868,7 @@ void Interpreter::lswi(UGeckoInstruction inst)
} }
const u32 temp_value = PowerPC::Read_U8(EA) << (24 - i); const u32 temp_value = PowerPC::Read_U8(EA) << (24 - i);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
PanicAlertFmt("DSI exception in lsw."); PanicAlertFmt("DSI exception in lsw.");
return; return;
@ -893,10 +889,8 @@ void Interpreter::lswi(UGeckoInstruction inst)
// FIXME: Should rollback if a DSI occurs // FIXME: Should rollback if a DSI occurs
void Interpreter::stswi(UGeckoInstruction inst) void Interpreter::stswi(UGeckoInstruction inst)
{ {
u32 EA; u32 EA = 0;
if (inst.RA == 0) if (inst.RA != 0)
EA = 0;
else
EA = rGPR[inst.RA]; EA = rGPR[inst.RA];
if (MSR.LE) if (MSR.LE)
@ -905,14 +899,12 @@ void Interpreter::stswi(UGeckoInstruction inst)
return; return;
} }
u32 n; u32 n = 32;
if (inst.NB == 0) if (inst.NB != 0)
n = 32;
else
n = inst.NB; n = inst.NB;
int r = inst.RS - 1; u32 r = u32{inst.RS} - 1;
int i = 0; u32 i = 0;
while (n > 0) while (n > 0)
{ {
if (i == 0) if (i == 0)
@ -921,7 +913,7 @@ void Interpreter::stswi(UGeckoInstruction inst)
r &= 31; r &= 31;
} }
PowerPC::Write_U8((rGPR[r] >> (24 - i)) & 0xFF, EA); PowerPC::Write_U8((rGPR[r] >> (24 - i)) & 0xFF, EA);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
return; return;
} }
@ -945,9 +937,9 @@ void Interpreter::stswx(UGeckoInstruction inst)
return; return;
} }
u32 n = (u8)PowerPC::ppcState.xer_stringctrl; u32 n = u8(PowerPC::ppcState.xer_stringctrl);
int r = inst.RS; u32 r = inst.RS;
int i = 0; u32 i = 0;
while (n > 0) while (n > 0)
{ {

View File

@ -57,13 +57,13 @@ const float m_quantizeTable[] = {
}; };
template <typename SType> template <typename SType>
SType ScaleAndClamp(double ps, u32 stScale) SType ScaleAndClamp(double ps, u32 st_scale)
{ {
float convPS = (float)ps * m_quantizeTable[stScale]; const float conv_ps = float(ps) * m_quantizeTable[st_scale];
constexpr float min = (float)std::numeric_limits<SType>::min(); constexpr float min = float(std::numeric_limits<SType>::min());
constexpr float max = (float)std::numeric_limits<SType>::max(); constexpr float max = float(std::numeric_limits<SType>::max());
return (SType)std::clamp(convPS, min, max); return SType(std::clamp(conv_ps, min, max));
} }
template <typename T> template <typename T>
@ -93,22 +93,22 @@ static std::pair<T, T> ReadPair(u32 addr);
template <> template <>
std::pair<u8, u8> ReadPair<u8>(u32 addr) std::pair<u8, u8> ReadPair<u8>(u32 addr)
{ {
u16 val = PowerPC::Read_U16(addr); const u16 val = PowerPC::Read_U16(addr);
return {(u8)(val >> 8), (u8)val}; return {u8(val >> 8), u8(val)};
} }
template <> template <>
std::pair<u16, u16> ReadPair<u16>(u32 addr) std::pair<u16, u16> ReadPair<u16>(u32 addr)
{ {
u32 val = PowerPC::Read_U32(addr); const u32 val = PowerPC::Read_U32(addr);
return {(u16)(val >> 16), (u16)val}; return {u16(val >> 16), u16(val)};
} }
template <> template <>
std::pair<u32, u32> ReadPair<u32>(u32 addr) std::pair<u32, u32> ReadPair<u32>(u32 addr)
{ {
u64 val = PowerPC::Read_U64(addr); const u64 val = PowerPC::Read_U64(addr);
return {(u32)(val >> 32), (u32)val}; return {u32(val >> 32), u32(val)};
} }
template <typename T> template <typename T>
@ -138,35 +138,35 @@ static void WritePair(T val1, T val2, u32 addr);
template <> template <>
void WritePair<u8>(u8 val1, u8 val2, u32 addr) void WritePair<u8>(u8 val1, u8 val2, u32 addr)
{ {
PowerPC::Write_U16(((u16)val1 << 8) | (u16)val2, addr); PowerPC::Write_U16((u16{val1} << 8) | u16{val2}, addr);
} }
template <> template <>
void WritePair<u16>(u16 val1, u16 val2, u32 addr) void WritePair<u16>(u16 val1, u16 val2, u32 addr)
{ {
PowerPC::Write_U32(((u32)val1 << 16) | (u32)val2, addr); PowerPC::Write_U32((u32{val1} << 16) | u32{val2}, addr);
} }
template <> template <>
void WritePair<u32>(u32 val1, u32 val2, u32 addr) void WritePair<u32>(u32 val1, u32 val2, u32 addr)
{ {
PowerPC::Write_U64(((u64)val1 << 32) | (u64)val2, addr); PowerPC::Write_U64((u64{val1} << 32) | u64{val2}, addr);
} }
template <typename T> template <typename T>
void QuantizeAndStore(double ps0, double ps1, u32 addr, u32 instW, u32 stScale) void QuantizeAndStore(double ps0, double ps1, u32 addr, u32 instW, u32 st_scale)
{ {
using U = std::make_unsigned_t<T>; using U = std::make_unsigned_t<T>;
U convPS0 = (U)ScaleAndClamp<T>(ps0, stScale); const U conv_ps0 = U(ScaleAndClamp<T>(ps0, st_scale));
if (instW) if (instW)
{ {
WriteUnpaired<U>(convPS0, addr); WriteUnpaired<U>(conv_ps0, addr);
} }
else else
{ {
U convPS1 = (U)ScaleAndClamp<T>(ps1, stScale); const U conv_ps1 = U(ScaleAndClamp<T>(ps1, st_scale));
WritePair<U>(convPS0, convPS1, addr); WritePair<U>(conv_ps0, conv_ps1, addr);
} }
} }
@ -174,20 +174,20 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins
u32 instW) u32 instW)
{ {
const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]); const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]);
const EQuantizeType stType = gqr.st_type; const EQuantizeType st_type = gqr.st_type;
const unsigned int stScale = gqr.st_scale; const u32 st_scale = gqr.st_scale;
const double ps0 = ppcs->ps[instRS].PS0AsDouble(); const double ps0 = ppcs->ps[instRS].PS0AsDouble();
const double ps1 = ppcs->ps[instRS].PS1AsDouble(); const double ps1 = ppcs->ps[instRS].PS1AsDouble();
switch (stType) switch (st_type)
{ {
case QUANTIZE_FLOAT: case QUANTIZE_FLOAT:
{ {
const u64 integral_ps0 = Common::BitCast<u64>(ps0); const u64 integral_ps0 = Common::BitCast<u64>(ps0);
const u32 conv_ps0 = ConvertToSingleFTZ(integral_ps0); const u32 conv_ps0 = ConvertToSingleFTZ(integral_ps0);
if (instW) if (instW != 0)
{ {
WriteUnpaired<u32>(conv_ps0, addr); WriteUnpaired<u32>(conv_ps0, addr);
} }
@ -202,19 +202,19 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins
} }
case QUANTIZE_U8: case QUANTIZE_U8:
QuantizeAndStore<u8>(ps0, ps1, addr, instW, stScale); QuantizeAndStore<u8>(ps0, ps1, addr, instW, st_scale);
break; break;
case QUANTIZE_U16: case QUANTIZE_U16:
QuantizeAndStore<u16>(ps0, ps1, addr, instW, stScale); QuantizeAndStore<u16>(ps0, ps1, addr, instW, st_scale);
break; break;
case QUANTIZE_S8: case QUANTIZE_S8:
QuantizeAndStore<s8>(ps0, ps1, addr, instW, stScale); QuantizeAndStore<s8>(ps0, ps1, addr, instW, st_scale);
break; break;
case QUANTIZE_S16: case QUANTIZE_S16:
QuantizeAndStore<s16>(ps0, ps1, addr, instW, stScale); QuantizeAndStore<s16>(ps0, ps1, addr, instW, st_scale);
break; break;
case QUANTIZE_INVALID1: case QUANTIZE_INVALID1:
@ -226,22 +226,22 @@ static void Helper_Quantize(const PowerPC::PowerPCState* ppcs, u32 addr, u32 ins
} }
template <typename T> template <typename T>
std::pair<double, double> LoadAndDequantize(u32 addr, u32 instW, u32 ldScale) std::pair<double, double> LoadAndDequantize(u32 addr, u32 instW, u32 ld_scale)
{ {
using U = std::make_unsigned_t<T>; using U = std::make_unsigned_t<T>;
float ps0, ps1; float ps0, ps1;
if (instW) if (instW != 0)
{ {
U value = ReadUnpaired<U>(addr); const U value = ReadUnpaired<U>(addr);
ps0 = (float)(T)(value)*m_dequantizeTable[ldScale]; ps0 = float(T(value)) * m_dequantizeTable[ld_scale];
ps1 = 1.0f; ps1 = 1.0f;
} }
else else
{ {
std::pair<U, U> value = ReadPair<U>(addr); const auto [first, second] = ReadPair<U>(addr);
ps0 = (float)(T)(value.first) * m_dequantizeTable[ldScale]; ps0 = float(T(first)) * m_dequantizeTable[ld_scale];
ps1 = (float)(T)(value.second) * m_dequantizeTable[ldScale]; ps1 = float(T(second)) * m_dequantizeTable[ld_scale];
} }
// ps0 and ps1 always contain finite and normal numbers. So we can just cast them to double // ps0 and ps1 always contain finite and normal numbers. So we can just cast them to double
return {static_cast<double>(ps0), static_cast<double>(ps1)}; return {static_cast<double>(ps0), static_cast<double>(ps1)};
@ -250,17 +250,17 @@ std::pair<double, double> LoadAndDequantize(u32 addr, u32 instW, u32 ldScale)
static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, u32 instRD, static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI, u32 instRD,
u32 instW) u32 instW)
{ {
UGQR gqr(ppcs->spr[SPR_GQR0 + instI]); const UGQR gqr(ppcs->spr[SPR_GQR0 + instI]);
EQuantizeType ldType = gqr.ld_type; const EQuantizeType ld_type = gqr.ld_type;
unsigned int ldScale = gqr.ld_scale; const u32 ld_scale = gqr.ld_scale;
double ps0 = 0.0; double ps0 = 0.0;
double ps1 = 0.0; double ps1 = 0.0;
switch (ldType) switch (ld_type)
{ {
case QUANTIZE_FLOAT: case QUANTIZE_FLOAT:
if (instW) if (instW != 0)
{ {
const u32 value = ReadUnpaired<u32>(addr); const u32 value = ReadUnpaired<u32>(addr);
ps0 = Common::BitCast<double>(ConvertToDouble(value)); ps0 = Common::BitCast<double>(ConvertToDouble(value));
@ -268,26 +268,26 @@ static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI,
} }
else else
{ {
const std::pair<u32, u32> value = ReadPair<u32>(addr); const auto [first, second] = ReadPair<u32>(addr);
ps0 = Common::BitCast<double>(ConvertToDouble(value.first)); ps0 = Common::BitCast<double>(ConvertToDouble(first));
ps1 = Common::BitCast<double>(ConvertToDouble(value.second)); ps1 = Common::BitCast<double>(ConvertToDouble(second));
} }
break; break;
case QUANTIZE_U8: case QUANTIZE_U8:
std::tie(ps0, ps1) = LoadAndDequantize<u8>(addr, instW, ldScale); std::tie(ps0, ps1) = LoadAndDequantize<u8>(addr, instW, ld_scale);
break; break;
case QUANTIZE_U16: case QUANTIZE_U16:
std::tie(ps0, ps1) = LoadAndDequantize<u16>(addr, instW, ldScale); std::tie(ps0, ps1) = LoadAndDequantize<u16>(addr, instW, ld_scale);
break; break;
case QUANTIZE_S8: case QUANTIZE_S8:
std::tie(ps0, ps1) = LoadAndDequantize<s8>(addr, instW, ldScale); std::tie(ps0, ps1) = LoadAndDequantize<s8>(addr, instW, ld_scale);
break; break;
case QUANTIZE_S16: case QUANTIZE_S16:
std::tie(ps0, ps1) = LoadAndDequantize<s16>(addr, instW, ldScale); std::tie(ps0, ps1) = LoadAndDequantize<s16>(addr, instW, ld_scale);
break; break;
case QUANTIZE_INVALID1: case QUANTIZE_INVALID1:
@ -299,7 +299,7 @@ static void Helper_Dequantize(PowerPC::PowerPCState* ppcs, u32 addr, u32 instI,
break; break;
} }
if (ppcs->Exceptions & EXCEPTION_DSI) if ((ppcs->Exceptions & EXCEPTION_DSI) != 0)
{ {
return; return;
} }
@ -315,7 +315,7 @@ void Interpreter::psq_l(UGeckoInstruction inst)
return; return;
} }
const u32 EA = inst.RA ? (rGPR[inst.RA] + inst.SIMM_12) : (u32)inst.SIMM_12; const u32 EA = inst.RA ? (rGPR[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12);
Helper_Dequantize(&PowerPC::ppcState, EA, inst.I, inst.RD, inst.W); Helper_Dequantize(&PowerPC::ppcState, EA, inst.I, inst.RD, inst.W);
} }
@ -327,13 +327,14 @@ void Interpreter::psq_lu(UGeckoInstruction inst)
return; return;
} }
const u32 EA = rGPR[inst.RA] + inst.SIMM_12; const u32 EA = rGPR[inst.RA] + u32(inst.SIMM_12);
Helper_Dequantize(&PowerPC::ppcState, EA, inst.I, inst.RD, inst.W); Helper_Dequantize(&PowerPC::ppcState, EA, inst.I, inst.RD, inst.W);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
return; return;
} }
rGPR[inst.RA] = EA; rGPR[inst.RA] = EA;
} }
@ -345,7 +346,7 @@ void Interpreter::psq_st(UGeckoInstruction inst)
return; return;
} }
const u32 EA = inst.RA ? (rGPR[inst.RA] + inst.SIMM_12) : (u32)inst.SIMM_12; const u32 EA = inst.RA ? (rGPR[inst.RA] + u32(inst.SIMM_12)) : u32(inst.SIMM_12);
Helper_Quantize(&PowerPC::ppcState, EA, inst.I, inst.RS, inst.W); Helper_Quantize(&PowerPC::ppcState, EA, inst.I, inst.RS, inst.W);
} }
@ -357,13 +358,14 @@ void Interpreter::psq_stu(UGeckoInstruction inst)
return; return;
} }
const u32 EA = rGPR[inst.RA] + inst.SIMM_12; const u32 EA = rGPR[inst.RA] + u32(inst.SIMM_12);
Helper_Quantize(&PowerPC::ppcState, EA, inst.I, inst.RS, inst.W); Helper_Quantize(&PowerPC::ppcState, EA, inst.I, inst.RS, inst.W);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
return; return;
} }
rGPR[inst.RA] = EA; rGPR[inst.RA] = EA;
} }
@ -384,10 +386,11 @@ void Interpreter::psq_lux(UGeckoInstruction inst)
const u32 EA = rGPR[inst.RA] + rGPR[inst.RB]; const u32 EA = rGPR[inst.RA] + rGPR[inst.RB];
Helper_Dequantize(&PowerPC::ppcState, EA, inst.Ix, inst.RD, inst.Wx); Helper_Dequantize(&PowerPC::ppcState, EA, inst.Ix, inst.RD, inst.Wx);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
return; return;
} }
rGPR[inst.RA] = EA; rGPR[inst.RA] = EA;
} }
@ -396,9 +399,10 @@ void Interpreter::psq_stux(UGeckoInstruction inst)
const u32 EA = rGPR[inst.RA] + rGPR[inst.RB]; const u32 EA = rGPR[inst.RA] + rGPR[inst.RB];
Helper_Quantize(&PowerPC::ppcState, EA, inst.Ix, inst.RS, inst.Wx); Helper_Quantize(&PowerPC::ppcState, EA, inst.Ix, inst.RS, inst.Wx);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
return; return;
} }
rGPR[inst.RA] = EA; rGPR[inst.RA] = EA;
} }

View File

@ -144,7 +144,7 @@ void Interpreter::ps_res(UGeckoInstruction inst)
const double ps1 = Common::ApproximateReciprocal(b); const double ps1 = Common::ApproximateReciprocal(b);
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRFSingle(ps0); PowerPC::UpdateFPRFSingle(float(ps0));
if (inst.Rc) if (inst.Rc)
PowerPC::ppcState.UpdateCR1(); PowerPC::ppcState.UpdateCR1();

View File

@ -61,7 +61,7 @@ void Interpreter::mtfsb1x(UGeckoInstruction inst)
const u32 bit = inst.CRBD; const u32 bit = inst.CRBD;
const u32 b = 0x80000000 >> bit; const u32 b = 0x80000000 >> bit;
if (b & FPSCR_ANY_X) if ((b & FPSCR_ANY_X) != 0)
SetFPException(&FPSCR, b); SetFPException(&FPSCR, b);
else else
FPSCR |= b; FPSCR |= b;
@ -93,7 +93,7 @@ void Interpreter::mtfsfx(UGeckoInstruction inst)
u32 m = 0; u32 m = 0;
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < 8; i++)
{ {
if (fm & (1U << i)) if ((fm & (1U << i)) != 0)
m |= (0xFU << (i * 4)); m |= (0xFU << (i * 4));
} }
@ -129,7 +129,7 @@ void Interpreter::mtcrf(UGeckoInstruction inst)
u32 mask = 0; u32 mask = 0;
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < 8; i++)
{ {
if (crm & (1U << i)) if ((crm & (1U << i)) != 0)
mask |= 0xFU << (i * 4); mask |= 0xFU << (i * 4);
} }
@ -214,9 +214,8 @@ void Interpreter::mtsrin(UGeckoInstruction inst)
void Interpreter::mftb(UGeckoInstruction inst) void Interpreter::mftb(UGeckoInstruction inst)
{ {
const u32 index = (inst.TBR >> 5) | ((inst.TBR & 0x1F) << 5); [[maybe_unused]] const u32 index = (inst.TBR >> 5) | ((inst.TBR & 0x1F) << 5);
DEBUG_ASSERT_MSG(POWERPC, (index == SPR_TL) || (index == SPR_TU), "Invalid mftb"); DEBUG_ASSERT_MSG(POWERPC, (index == SPR_TL) || (index == SPR_TU), "Invalid mftb");
(void)index;
mfspr(inst); mfspr(inst);
} }
@ -389,7 +388,8 @@ void Interpreter::mtspr(UGeckoInstruction inst)
break; break;
case SPR_DEC: case SPR_DEC:
if (!(old_value >> 31) && (rGPR[inst.RD] >> 31)) // top bit from 0 to 1 // Top bit from 0 to 1
if ((old_value >> 31) == 0 && (rGPR[inst.RD] >> 31) != 0)
{ {
INFO_LOG_FMT(POWERPC, "Software triggered Decrementer exception"); INFO_LOG_FMT(POWERPC, "Software triggered Decrementer exception");
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER; PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
@ -487,50 +487,66 @@ void Interpreter::mtspr(UGeckoInstruction inst)
void Interpreter::crand(UGeckoInstruction inst) void Interpreter::crand(UGeckoInstruction inst)
{ {
PowerPC::ppcState.cr.SetBit(inst.CRBD, PowerPC::ppcState.cr.GetBit(inst.CRBA) & const u32 a = PowerPC::ppcState.cr.GetBit(inst.CRBA);
PowerPC::ppcState.cr.GetBit(inst.CRBB)); const u32 b = PowerPC::ppcState.cr.GetBit(inst.CRBB);
PowerPC::ppcState.cr.SetBit(inst.CRBD, a & b);
} }
void Interpreter::crandc(UGeckoInstruction inst) void Interpreter::crandc(UGeckoInstruction inst)
{ {
PowerPC::ppcState.cr.SetBit(inst.CRBD, PowerPC::ppcState.cr.GetBit(inst.CRBA) & const u32 a = PowerPC::ppcState.cr.GetBit(inst.CRBA);
(1 ^ PowerPC::ppcState.cr.GetBit(inst.CRBB))); const u32 b = PowerPC::ppcState.cr.GetBit(inst.CRBB);
PowerPC::ppcState.cr.SetBit(inst.CRBD, a & (1 ^ b));
} }
void Interpreter::creqv(UGeckoInstruction inst) void Interpreter::creqv(UGeckoInstruction inst)
{ {
PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (PowerPC::ppcState.cr.GetBit(inst.CRBA) ^ const u32 a = PowerPC::ppcState.cr.GetBit(inst.CRBA);
PowerPC::ppcState.cr.GetBit(inst.CRBB))); const u32 b = PowerPC::ppcState.cr.GetBit(inst.CRBB);
PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (a ^ b));
} }
void Interpreter::crnand(UGeckoInstruction inst) void Interpreter::crnand(UGeckoInstruction inst)
{ {
PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (PowerPC::ppcState.cr.GetBit(inst.CRBA) & const u32 a = PowerPC::ppcState.cr.GetBit(inst.CRBA);
PowerPC::ppcState.cr.GetBit(inst.CRBB))); const u32 b = PowerPC::ppcState.cr.GetBit(inst.CRBB);
PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (a & b));
} }
void Interpreter::crnor(UGeckoInstruction inst) void Interpreter::crnor(UGeckoInstruction inst)
{ {
PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (PowerPC::ppcState.cr.GetBit(inst.CRBA) | const u32 a = PowerPC::ppcState.cr.GetBit(inst.CRBA);
PowerPC::ppcState.cr.GetBit(inst.CRBB))); const u32 b = PowerPC::ppcState.cr.GetBit(inst.CRBB);
PowerPC::ppcState.cr.SetBit(inst.CRBD, 1 ^ (a | b));
} }
void Interpreter::cror(UGeckoInstruction inst) void Interpreter::cror(UGeckoInstruction inst)
{ {
PowerPC::ppcState.cr.SetBit( const u32 a = PowerPC::ppcState.cr.GetBit(inst.CRBA);
inst.CRBD, (PowerPC::ppcState.cr.GetBit(inst.CRBA) | PowerPC::ppcState.cr.GetBit(inst.CRBB))); const u32 b = PowerPC::ppcState.cr.GetBit(inst.CRBB);
PowerPC::ppcState.cr.SetBit(inst.CRBD, a | b);
} }
void Interpreter::crorc(UGeckoInstruction inst) void Interpreter::crorc(UGeckoInstruction inst)
{ {
PowerPC::ppcState.cr.SetBit(inst.CRBD, (PowerPC::ppcState.cr.GetBit(inst.CRBA) | const u32 a = PowerPC::ppcState.cr.GetBit(inst.CRBA);
(1 ^ PowerPC::ppcState.cr.GetBit(inst.CRBB)))); const u32 b = PowerPC::ppcState.cr.GetBit(inst.CRBB);
PowerPC::ppcState.cr.SetBit(inst.CRBD, a | (1 ^ b));
} }
void Interpreter::crxor(UGeckoInstruction inst) void Interpreter::crxor(UGeckoInstruction inst)
{ {
PowerPC::ppcState.cr.SetBit( const u32 a = PowerPC::ppcState.cr.GetBit(inst.CRBA);
inst.CRBD, (PowerPC::ppcState.cr.GetBit(inst.CRBA) ^ PowerPC::ppcState.cr.GetBit(inst.CRBB))); const u32 b = PowerPC::ppcState.cr.GetBit(inst.CRBB);
PowerPC::ppcState.cr.SetBit(inst.CRBD, a ^ b);
} }
void Interpreter::mcrf(UGeckoInstruction inst) void Interpreter::mcrf(UGeckoInstruction inst)