Common: Sign extend w/func not chained casts.

Should be clearer to read and easier to get right.
This commit is contained in:
Unknown W. Brackets 2021-01-31 01:25:52 -08:00
parent 8205f9b6f2
commit 1b00da2f3a
23 changed files with 92 additions and 60 deletions

View File

@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Common/Data/Convert/SmallDataConvert.h"
#include "ColorConv.h"
// NEON is in a separate file so that it can be compiled with a runtime check.
#include "ColorConvNEON.h"
@ -487,8 +488,8 @@ void ConvertRGBA5551ToBGRA8888(u32 *dst, const u16 *src, u32 numPixels) {
u32 r = Convert5To8(c & 0x001f);
u32 g = Convert5To8((c >> 5) & 0x001f);
u32 b = Convert5To8((c >> 10) & 0x001f);
// We force an arithmetic shift to get the sign bits/
u32 a = ((s32)(s16)c) & 0xff000000;
// We force an arithmetic shift to get the sign bits.
u32 a = SignExtend16To32(c) & 0xff000000;
dst[x] = a | (r << 16) | (g << 8) | b;
}

View File

@ -180,3 +180,16 @@ inline void ExpandFloat24x3ToFloat4(float dest[4], const uint32_t src[3]) {
inline uint32_t BytesToUint32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
return (a) | (b << 8) | (c << 16) | (d << 24);
}
constexpr uint32_t SignExtend8To32(uint32_t value) {
// This extends this sign at the 8th bit to the other 24 bits.
int32_t signedValue = (int8_t)(value & 0xFF);
// We return as unsigned because we're likely just interested in the bits.
return (uint32_t)signedValue;
}
constexpr uint32_t SignExtend16To32(uint32_t value) {
// Same as SignExtend8to32, but from the 16th bit.
int32_t signedValue = (int16_t)(value & 0xFFFF);
return (uint32_t)signedValue;
}

View File

@ -136,7 +136,7 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs)
DEBUG_LOG(LOADER,"Corresponding lo found at %08x", corrLoAddr);
}
if (Memory::IsValidAddress(corrLoAddr)) {
s16 lo = (s32)(s16)(u16)(Memory::ReadUnchecked_U32(corrLoAddr) & 0xFFFF); //signed??
s16 lo = (s16)Memory::ReadUnchecked_U16(corrLoAddr);
cur += lo;
cur += relocateTo;
addrToHiLo(cur, hi, lo);

View File

@ -21,6 +21,7 @@
#include "zlib.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Serialize/Serializer.h"
#include "Common/Serialize/SerializeFuncs.h"
#include "Common/Serialize/SerializeSet.h"
@ -625,7 +626,7 @@ static void WriteVarSymbol(WriteVarSymbolState &state, u32 exportAddress, u32 re
case R_MIPS_LO16:
{
// Sign extend the existing low value (e.g. from addiu.)
const u32 offsetLo = (s32)(s16)(u16)(relocData & 0xFFFF);
const u32 offsetLo = SignExtend16To32(relocData);
u32 full = exportAddress;
// This is only used in the error case (no hi/wrong hi.)
if (!reverse) {

View File

@ -20,12 +20,13 @@
#include <algorithm>
#include "Common/BitSet.h"
#include "Common/CPUDetect.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MIPS/ARM/ArmJit.h"
#include "Core/MIPS/ARM/ArmRegCache.h"
#include "Common/CPUDetect.h"
#include "Common/BitSet.h"
using namespace MIPSAnalyst;
@ -75,9 +76,9 @@ namespace MIPSComp
void ArmJit::Comp_IType(MIPSOpcode op)
{
CONDITIONAL_DISABLE(ALU_IMM);
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
u32 uimm = op & 0xFFFF;
u32 suimm = (u32)(s32)simm;
u32 suimm = SignExtend16To32(op);
s32 simm = (s32)suimm;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@ -601,9 +602,9 @@ namespace MIPSComp
return;
switch ((op >> 6) & 31) {
case 16: // seb // R(rd) = (u32)(s32)(s8)(u8)R(rt);
case 16: // seb // R(rd) = SignExtend8To32(R(rt));
if (gpr.IsImm(rt)) {
gpr.SetImm(rd, (s32)(s8)(u8)gpr.GetImm(rt));
gpr.SetImm(rd, SignExtend8To32(gpr.GetImm(rt)));
return;
}
gpr.MapDirtyIn(rd, rt);
@ -612,7 +613,7 @@ namespace MIPSComp
case 24: // seh
if (gpr.IsImm(rt)) {
gpr.SetImm(rd, (s32)(s16)(u16)gpr.GetImm(rt));
gpr.SetImm(rd, SignExtend16To32(gpr.GetImm(rt)));
return;
}
gpr.MapDirtyIn(rd, rt);

View File

@ -18,6 +18,7 @@
#include "ppsspp_config.h"
#if PPSSPP_ARCH(ARM)
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Profiler/Profiler.h"
#include "Core/Config.h"
@ -47,9 +48,8 @@
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
#define TARGET16 ((int)((uint32_t)(int)_IMM16 << 2))
#define TARGET16 ((int)(SignExtend16To32(op) << 2))
#define TARGET26 (_IMM26 << 2)
#define LOOPOPTIMIZATION 0

View File

@ -19,6 +19,8 @@
#if PPSSPP_ARCH(ARM)
#include <cmath>
#include "Common/CPUDetect.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Math/math_util.h"
#include "Core/Compatibility.h"
@ -30,7 +32,6 @@
#include "Core/MIPS/MIPSTables.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Common/CPUDetect.h"
#include "Core/MIPS/ARM/ArmJit.h"
#include "Core/MIPS/ARM/ArmRegCache.h"
@ -2087,7 +2088,7 @@ namespace MIPSComp
u8 dreg;
GetVectorRegs(&dreg, V_Single, _VT);
s32 imm = (s32)(s16)(u16)(op & 0xFFFF);
s32 imm = (s32)SignExtend16To32(op);
fpr.MapRegV(dreg, MAP_DIRTY | MAP_NOINIT);
MOVI2F(fpr.V(dreg), (float)imm, SCRATCHREG1);

View File

@ -30,6 +30,7 @@
#include <cmath>
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Math/math_util.h"
#include "Common/CPUDetect.h"
@ -1347,7 +1348,7 @@ void ArmJit::CompNEON_Viim(MIPSOpcode op) {
DestARMReg vt = NEONMapPrefixD(_VT, V_Single, MAP_NOINIT | MAP_DIRTY);
s32 imm = (s32)(s16)(u16)(op & 0xFFFF);
s32 imm = (s32)SignExtend16To32(op);
// TODO: Optimize for low registers.
MOVI2F(S0, (float)imm, R0);
VMOV_neon(vt.rd, D0);

View File

@ -22,6 +22,7 @@
#include "Common/BitSet.h"
#include "Common/CPUDetect.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MIPS/ARM64/Arm64Jit.h"
@ -72,9 +73,9 @@ void Arm64Jit::CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARM64XEm
void Arm64Jit::Comp_IType(MIPSOpcode op) {
CONDITIONAL_DISABLE(ALU_IMM);
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
u32 uimm = op & 0xFFFF;
u32 suimm = (u32)(s32)simm;
u32 suimm = SignExtend16To32(op);
s32 simm = (s32)suimm;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@ -488,9 +489,9 @@ void Arm64Jit::Comp_Allegrex(MIPSOpcode op) {
return;
switch ((op >> 6) & 31) {
case 16: // seb // R(rd) = (u32)(s32)(s8)(u8)R(rt);
case 16: // seb // R(rd) = SignExtend8To32(R(rt));
if (gpr.IsImm(rt)) {
gpr.SetImm(rd, (s32)(s8)(u8)gpr.GetImm(rt));
gpr.SetImm(rd, SignExtend8To32(gpr.GetImm(rt)));
return;
}
gpr.MapDirtyIn(rd, rt);
@ -499,7 +500,7 @@ void Arm64Jit::Comp_Allegrex(MIPSOpcode op) {
case 24: // seh
if (gpr.IsImm(rt)) {
gpr.SetImm(rd, (s32)(s16)(u16)gpr.GetImm(rt));
gpr.SetImm(rd, SignExtend16To32(gpr.GetImm(rt)));
return;
}
gpr.MapDirtyIn(rd, rt);

View File

@ -18,6 +18,7 @@
#include "ppsspp_config.h"
#if PPSSPP_ARCH(ARM64)
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Profiler/Profiler.h"
#include "Core/Config.h"
@ -47,9 +48,8 @@
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
#define TARGET16 ((int)((uint32_t)(int)_IMM16 << 2))
#define TARGET16 ((int)(SignExtend16To32(op) << 2))
#define TARGET26 (_IMM26 << 2)
#define LOOPOPTIMIZATION 0

View File

@ -19,6 +19,9 @@
#if PPSSPP_ARCH(ARM64)
#include <cmath>
#include "Common/Arm64Emitter.h"
#include "Common/CPUDetect.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Math/math_util.h"
#include "Core/Compatibility.h"
@ -30,8 +33,6 @@
#include "Core/MIPS/MIPSTables.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Common/CPUDetect.h"
#include "Common/Arm64Emitter.h"
#include "Core/MIPS/ARM64/Arm64Jit.h"
#include "Core/MIPS/ARM64/Arm64RegCache.h"
@ -1811,7 +1812,7 @@ namespace MIPSComp {
u8 dreg;
GetVectorRegs(&dreg, V_Single, _VT);
s32 imm = (s32)(s16)(u16)(op & 0xFFFF);
s32 imm = (s32)SignExtend16To32(op);
fpr.MapRegV(dreg, MAP_DIRTY | MAP_NOINIT);
fp.MOVI2F(fpr.V(dreg), (float)imm, SCRATCH1);

View File

@ -274,7 +274,7 @@ void IRFrontend::Comp_Allegrex(MIPSOpcode op) {
return;
switch ((op >> 6) & 31) {
case 16: // seb // R(rd) = (u32)(s32)(s8)(u8)R(rt);
case 16: // seb // R(rd) = SignExtend8To32(R(rt));
ir.Write(IROp::Ext8to32, rd, rt);
break;

View File

@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Profiler/Profiler.h"
#include "Core/Reporting.h"
@ -40,9 +41,8 @@
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
#define TARGET16 ((int)((uint32_t)(int)_IMM16 << 2))
#define TARGET16 ((int)(SignExtend16To32(op) << 2))
#define TARGET26 (_IMM26 << 2)
#define LOOPOPTIMIZATION 0

View File

@ -17,9 +17,9 @@
#include <cmath>
#include "Common/Math/math_util.h"
#include "Common/CPUDetect.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Math/math_util.h"
#include "Core/Compatibility.h"
#include "Core/Config.h"
#include "Core/MemMap.h"
@ -1778,7 +1778,7 @@ namespace MIPSComp {
// Vector integer immediate
// d[0] = float(imm)
s32 imm = (s32)(s16)(u16)(op & 0xFFFF);
s32 imm = (s32)SignExtend16To32(op);
u8 dreg;
GetVectorRegsPrefixD(&dreg, V_Single, _VT);
ir.Write(IROp::SetConstF, dreg, ir.AddConstantFloat((float)imm));

View File

@ -2,9 +2,10 @@
#include <cmath>
#include "ppsspp_config.h"
#include "Common/Math/math_util.h"
#include "Common/Common.h"
#include "Common/BitScan.h"
#include "Common/Common.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Math/math_util.h"
#ifdef _M_SSE
#include <emmintrin.h>
@ -126,10 +127,10 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) {
mips->r[inst->dest] = ~mips->r[inst->src1];
break;
case IROp::Ext8to32:
mips->r[inst->dest] = (s32)(s8)mips->r[inst->src1];
mips->r[inst->dest] = SignExtend8To32(mips->r[inst->src1]);
break;
case IROp::Ext16to32:
mips->r[inst->dest] = (s32)(s16)mips->r[inst->src1];
mips->r[inst->dest] = SignExtend16To32(mips->r[inst->src1]);
break;
case IROp::ReverseBits:
mips->r[inst->dest] = ReverseBits32(mips->r[inst->src1]);
@ -139,13 +140,13 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) {
mips->r[inst->dest] = Memory::ReadUnchecked_U8(mips->r[inst->src1] + inst->constant);
break;
case IROp::Load8Ext:
mips->r[inst->dest] = (s32)(s8)Memory::ReadUnchecked_U8(mips->r[inst->src1] + inst->constant);
mips->r[inst->dest] = SignExtend8To32(Memory::ReadUnchecked_U8(mips->r[inst->src1] + inst->constant));
break;
case IROp::Load16:
mips->r[inst->dest] = Memory::ReadUnchecked_U16(mips->r[inst->src1] + inst->constant);
break;
case IROp::Load16Ext:
mips->r[inst->dest] = (s32)(s16)Memory::ReadUnchecked_U16(mips->r[inst->src1] + inst->constant);
mips->r[inst->dest] = SignExtend16To32(Memory::ReadUnchecked_U16(mips->r[inst->src1] + inst->constant));
break;
case IROp::Load32:
mips->r[inst->dest] = Memory::ReadUnchecked_U32(mips->r[inst->src1] + inst->constant);

View File

@ -3,6 +3,7 @@
#include <utility>
#include "Common/BitSet.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Log.h"
#include "Core/MIPS/IR/IRInterpreter.h"
#include "Core/MIPS/IR/IRPassSimplify.h"
@ -36,8 +37,8 @@ u32 Evaluate(u32 a, IROp op) {
case IROp::Neg: return -(s32)a;
case IROp::BSwap16: return ((a & 0xFF00FF00) >> 8) | ((a & 0x00FF00FF) << 8);
case IROp::BSwap32: return swap32(a);
case IROp::Ext8to32: return (u32)(s32)(s8)(u8)a;
case IROp::Ext16to32: return (u32)(s32)(s16)(u16)a;
case IROp::Ext8to32: return SignExtend8To32(a);
case IROp::Ext16to32: return SignExtend16To32(a);
case IROp::ReverseBits: return ReverseBits32(a);
case IROp::Clz: {
int x = 31;

View File

@ -18,6 +18,7 @@
#pragma once
#include "Common/CommonTypes.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Core/MIPS/MIPS.h"
// Invalid branch target address
@ -52,6 +53,13 @@
#define MIPS_GET_VS(op) ((op>>8) & 0x7F)
#define MIPS_GET_VT(op) ((op>>16) & 0x7F)
inline uint32_t SignExtend8To32(MIPSOpcode op) {
return SignExtend8To32(op.encoding);
}
inline uint32_t SignExtend16To32(MIPSOpcode op) {
return SignExtend16To32(op.encoding);
}
namespace MIPSCodeUtils
{

View File

@ -19,6 +19,7 @@
#include "Core/HLE/HLE.h"
#include "Core/MemMap.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MIPS/MIPSDis.h"
#include "Core/MIPS/MIPSTables.h"
#include "Core/MIPS/MIPSDebugInterface.h"
@ -171,9 +172,9 @@ namespace MIPSDis
void Dis_IType(MIPSOpcode op, char *out)
{
s32 simm = (s32)(s16)(op & 0xFFFF);
u32 uimm = (u32)(u16)(op & 0xFFFF);
u32 suimm = (u32)simm;
u32 uimm = op & 0xFFFF;
u32 suimm = SignExtend16To32(op);
s32 simm = (s32)suimm;
int rt = _RT;
int rs = _RS;

View File

@ -17,6 +17,7 @@
#include <cmath>
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Math/math_util.h"
#include "Common/BitSet.h"
@ -27,6 +28,7 @@
#include "Core/Host.h"
#include "Core/MemMap.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/MIPS/MIPSInt.h"
#include "Core/MIPS/MIPSTables.h"
#include "Core/Reporting.h"
@ -295,10 +297,9 @@ namespace MIPSInt
void Int_IType(MIPSOpcode op)
{
s32 simm = (s32)(s16)(op & 0xFFFF);
u32 uimm = (u32)(u16)(op & 0xFFFF);
u32 suimm = (u32)simm;
u32 uimm = op & 0xFFFF;
u32 suimm = SignExtend16To32(op);
s32 simm = (s32)suimm;
int rt = _RT;
int rs = _RS;
@ -411,8 +412,8 @@ namespace MIPSInt
switch (op >> 26)
{
case 32: R(rt) = (u32)(s32)(s8) Memory::Read_U8(addr); break; //lb
case 33: R(rt) = (u32)(s32)(s16)Memory::Read_U16(addr); break; //lh
case 32: R(rt) = SignExtend8To32(Memory::Read_U8(addr)); break; //lb
case 33: R(rt) = SignExtend16To32(Memory::Read_U16(addr)); break; //lh
case 35: R(rt) = Memory::Read_U32(addr); break; //lw
case 36: R(rt) = Memory::Read_U8 (addr); break; //lbu
case 37: R(rt) = Memory::Read_U16(addr); break; //lhu
@ -738,7 +739,7 @@ namespace MIPSInt
switch((op>>6)&31)
{
case 16: // seb
R(rd) = (u32)(s32)(s8)(u8)R(rt);
R(rd) = SignExtend8To32(R(rt));
break;
case 20: // bitrev
@ -756,7 +757,7 @@ namespace MIPSInt
break;
case 24: // seh
R(rd) = (u32)(s32)(s16)(u16)R(rt);
R(rd) = SignExtend16To32(R(rt));
break;
default:

View File

@ -798,10 +798,10 @@ namespace MIPSComp
switch ((op >> 6) & 31)
{
case 16: // seb // R(rd) = (u32)(s32)(s8)(u8)R(rt);
case 16: // seb // R(rd) = SignExtend8To32(R(rt));
if (gpr.IsImm(rt))
{
gpr.SetImm(rd, (u32)(s32)(s8)(u8)gpr.GetImm(rt));
gpr.SetImm(rd, SignExtend8To32(gpr.GetImm(rt)));
break;
}
@ -876,10 +876,10 @@ namespace MIPSComp
gpr.UnlockAll();
break;
case 24: // seh // R(rd) = (u32)(s32)(s16)(u16)R(rt);
case 24: // seh // R(rd) = SignExtend16To32(R(rt));
if (gpr.IsImm(rt))
{
gpr.SetImm(rd, (u32)(s32)(s16)(u16)gpr.GetImm(rt));
gpr.SetImm(rd, SignExtend16To32(gpr.GetImm(rt)));
break;
}

View File

@ -18,6 +18,7 @@
#include "ppsspp_config.h"
#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Profiler/Profiler.h"
#include "Core/Config.h"
@ -46,9 +47,8 @@
#define _SA MIPS_GET_SA(op)
#define _POS ((op>> 6) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define _IMM16 (signed short)(op & 0xFFFF)
#define _IMM26 (op & 0x03FFFFFF)
#define TARGET16 ((int)((uint32_t)(int)_IMM16 << 2))
#define TARGET16 ((int)(SignExtend16To32(op) << 2))
#define TARGET26 (_IMM26 << 2)
#define LOOPOPTIMIZATION 0

View File

@ -309,11 +309,11 @@ namespace MIPSComp {
CompITypeMemRead(op, 32, &XEmitter::MOVZX, safeMemFuncs.readU32);
break;
case 32: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb
case 32: //R(rt) = SignExtend8To32 (ReadMem8 (addr)); break; //lb
CompITypeMemRead(op, 8, &XEmitter::MOVSX, safeMemFuncs.readU8);
break;
case 33: //R(rt) = (u32)(s32)(s16)ReadMem16(addr); break; //lh
case 33: //R(rt) = SignExtend16To32(ReadMem16(addr)); break; //lh
CompITypeMemRead(op, 16, &XEmitter::MOVSX, safeMemFuncs.readU16);
break;

View File

@ -3452,7 +3452,7 @@ void Jit::Comp_Viim(MIPSOpcode op) {
// Flush SIMD.
fpr.SimpleRegsV(&dreg, V_Single, MAP_NOINIT | MAP_DIRTY);
s32 imm = (s32)(s16)(u16)(op & 0xFFFF);
s32 imm = (s32)SignExtend16To32(op);
FP32 fp;
fp.f = (float)imm;
MOV(32, R(TEMPREG), Imm32(fp.u));