mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-31 12:31:45 +01:00
Move rotate/cntlz/cnttz helpers to Utilities/asm.h
This commit is contained in:
parent
ee96807305
commit
ed9fb8405b
171
Utilities/asm.h
Normal file
171
Utilities/asm.h
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
inline u32 cntlz32(u32 arg, bool nonzero = false)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
ulong res;
|
||||||
|
return _BitScanReverse(&res, arg) || nonzero ? res ^ 31 : 32;
|
||||||
|
#else
|
||||||
|
return arg || nonzero ? __builtin_clz(arg) : 32;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 cntlz64(u64 arg, bool nonzero = false)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
ulong res;
|
||||||
|
return _BitScanReverse64(&res, arg) || nonzero ? res ^ 63 : 64;
|
||||||
|
#else
|
||||||
|
return arg || nonzero ? __builtin_clzll(arg) : 64;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32 cnttz32(u32 arg, bool nonzero = false)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
ulong res;
|
||||||
|
return _BitScanForward(&res, arg) || nonzero ? res : 32;
|
||||||
|
#else
|
||||||
|
return arg || nonzero ? __builtin_ctz(arg) : 32;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 cnttz64(u64 arg, bool nonzero = false)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
ulong res;
|
||||||
|
return _BitScanForward64(&res, arg) || nonzero ? res : 64;
|
||||||
|
#else
|
||||||
|
return arg || nonzero ? __builtin_ctzll(arg) : 64;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate helpers
|
||||||
|
#if defined(__GNUG__)
|
||||||
|
|
||||||
|
inline u8 rol8(u8 x, u8 n)
|
||||||
|
{
|
||||||
|
u8 result = x;
|
||||||
|
__asm__("rolb %[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 ror8(u8 x, u8 n)
|
||||||
|
{
|
||||||
|
u8 result = x;
|
||||||
|
__asm__("rorb %[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u16 rol16(u16 x, u16 n)
|
||||||
|
{
|
||||||
|
u16 result = x;
|
||||||
|
__asm__("rolw %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u16 ror16(u16 x, u16 n)
|
||||||
|
{
|
||||||
|
u16 result = x;
|
||||||
|
__asm__("rorw %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32 rol32(u32 x, u32 n)
|
||||||
|
{
|
||||||
|
u32 result = x;
|
||||||
|
__asm__("roll %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32 ror32(u32 x, u32 n)
|
||||||
|
{
|
||||||
|
u32 result = x;
|
||||||
|
__asm__("rorl %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 rol64(u64 x, u64 n)
|
||||||
|
{
|
||||||
|
u64 result = x;
|
||||||
|
__asm__("rolq %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 ror64(u64 x, u64 n)
|
||||||
|
{
|
||||||
|
u64 result = x;
|
||||||
|
__asm__("rorq %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 umulh64(u64 a, u64 b)
|
||||||
|
{
|
||||||
|
u64 result;
|
||||||
|
__asm__("mulq %[b]" : "=d"(result) : [a] "a"(a), [b] "rm"(b));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline s64 mulh64(s64 a, s64 b)
|
||||||
|
{
|
||||||
|
s64 result;
|
||||||
|
__asm__("imulq %[b]" : "=d"(result) : [a] "a"(a), [b] "rm"(b));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
inline u8 rol8(u8 x, u8 n)
|
||||||
|
{
|
||||||
|
return _rotl8(x, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u8 ror8(u8 x, u8 n)
|
||||||
|
{
|
||||||
|
return _rotr8(x, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u16 rol16(u16 x, u16 n)
|
||||||
|
{
|
||||||
|
return _rotl16(x, (u8)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u16 ror16(u16 x, u16 n)
|
||||||
|
{
|
||||||
|
return _rotr16(x, (u8)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32 rol32(u32 x, u32 n)
|
||||||
|
{
|
||||||
|
return _rotl(x, (int)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32 ror32(u32 x, u32 n)
|
||||||
|
{
|
||||||
|
return _rotr(x, (int)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 rol64(u64 x, u64 n)
|
||||||
|
{
|
||||||
|
return _rotl64(x, (int)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 ror64(u64 x, u64 n)
|
||||||
|
{
|
||||||
|
return _rotr64(x, (int)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u64 umulh64(u64 x, u64 y)
|
||||||
|
{
|
||||||
|
return __umulh(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline s64 mulh64(s64 x, s64 y)
|
||||||
|
{
|
||||||
|
return __mulh(x, y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace utils
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "asm.h"
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -56,7 +57,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
|||||||
|
|
||||||
const auto write_octal = [&](u64 value, u64 min_num)
|
const auto write_octal = [&](u64 value, u64 min_num)
|
||||||
{
|
{
|
||||||
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (cntlz64(value | 1, true) + 2) / 3), '0');
|
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (utils::cntlz64(value | 1, true) + 2) / 3), '0');
|
||||||
|
|
||||||
// Write in reversed order
|
// Write in reversed order
|
||||||
for (auto i = out.rbegin(); value; i++, value /= 8)
|
for (auto i = out.rbegin(); value; i++, value /= 8)
|
||||||
@ -67,8 +68,8 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
|||||||
|
|
||||||
const auto write_hex = [&](u64 value, bool upper, u64 min_num)
|
const auto write_hex = [&](u64 value, bool upper, u64 min_num)
|
||||||
{
|
{
|
||||||
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - cntlz64(value | 1, true) / 4), '0');
|
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - utils::cntlz64(value | 1, true) / 4), '0');
|
||||||
|
|
||||||
// Write in reversed order
|
// Write in reversed order
|
||||||
for (auto i = out.rbegin(); value; i++, value /= 16)
|
for (auto i = out.rbegin(); value; i++, value /= 16)
|
||||||
{
|
{
|
||||||
@ -141,7 +142,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
|||||||
{
|
{
|
||||||
ctx.width = read_decimal(ch - '0');
|
ctx.width = read_decimal(ch - '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +158,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
|||||||
ctx.width = std::abs(warg);
|
ctx.width = std::abs(warg);
|
||||||
ctx.left |= warg < 0;
|
ctx.left |= warg < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +308,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
|||||||
|
|
||||||
const std::size_t start = out.size();
|
const std::size_t start = out.size();
|
||||||
const std::size_t size1 = src.fmt_string(out, ctx.args);
|
const std::size_t size1 = src.fmt_string(out, ctx.args);
|
||||||
|
|
||||||
if (ctx.dot && size1 > ctx.prec)
|
if (ctx.dot && size1 > ctx.prec)
|
||||||
{
|
{
|
||||||
// Shrink if necessary
|
// Shrink if necessary
|
||||||
@ -576,7 +577,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
|||||||
// Add padding if necessary
|
// Add padding if necessary
|
||||||
out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' ');
|
out.insert(ctx.left ? out.end() : out.begin() + start, ctx.width - size2, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
src.skip(ctx.args);
|
src.skip(ctx.args);
|
||||||
ctx = {0};
|
ctx = {0};
|
||||||
break;
|
break;
|
||||||
|
@ -433,46 +433,6 @@ struct offset32_detail<T3 T4::*>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline u32 cntlz32(u32 arg, bool nonzero = false)
|
|
||||||
{
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
ulong res;
|
|
||||||
return _BitScanReverse(&res, arg) || nonzero ? res ^ 31 : 32;
|
|
||||||
#else
|
|
||||||
return arg || nonzero ? __builtin_clzll(arg) - 32 : 32;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u64 cntlz64(u64 arg, bool nonzero = false)
|
|
||||||
{
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
ulong res;
|
|
||||||
return _BitScanReverse64(&res, arg) || nonzero ? res ^ 63 : 64;
|
|
||||||
#else
|
|
||||||
return arg || nonzero ? __builtin_clzll(arg) : 64;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u32 cnttz32(u32 arg, bool nonzero = false)
|
|
||||||
{
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
ulong res;
|
|
||||||
return _BitScanForward(&res, arg) || nonzero ? res : 32;
|
|
||||||
#else
|
|
||||||
return arg || nonzero ? __builtin_ctzll(arg) : 32;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u64 cnttz64(u64 arg, bool nonzero = false)
|
|
||||||
{
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
ulong res;
|
|
||||||
return _BitScanForward64(&res, arg) || nonzero ? res : 64;
|
|
||||||
#else
|
|
||||||
return arg || nonzero ? __builtin_ctzll(arg) : 64;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function, used by ""_u16, ""_u32, ""_u64
|
// Helper function, used by ""_u16, ""_u32, ""_u64
|
||||||
constexpr u8 to_u8(char c)
|
constexpr u8 to_u8(char c)
|
||||||
{
|
{
|
||||||
@ -848,89 +808,3 @@ inline void busy_wait(std::size_t cycles = 3000)
|
|||||||
const u64 s = __rdtsc();
|
const u64 s = __rdtsc();
|
||||||
do _mm_pause(); while (__rdtsc() - s < cycles);
|
do _mm_pause(); while (__rdtsc() - s < cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate helpers
|
|
||||||
#if defined(__GNUG__)
|
|
||||||
|
|
||||||
inline u8 rol8(u8 x, u8 n)
|
|
||||||
{
|
|
||||||
u8 result = x;
|
|
||||||
__asm__("rolb %[n], %[result]" : [result] "+g" (result) : [n] "c" (n));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u8 ror8(u8 x, u8 n)
|
|
||||||
{
|
|
||||||
u8 result = x;
|
|
||||||
__asm__("rorb %[n], %[result]" : [result] "+g" (result) : [n] "c" (n));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u16 rol16(u16 x, u16 n)
|
|
||||||
{
|
|
||||||
u16 result = x;
|
|
||||||
__asm__("rolw %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u16 ror16(u16 x, u16 n)
|
|
||||||
{
|
|
||||||
u16 result = x;
|
|
||||||
__asm__("rorw %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u32 rol32(u32 x, u32 n)
|
|
||||||
{
|
|
||||||
u32 result = x;
|
|
||||||
__asm__("roll %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u32 ror32(u32 x, u32 n)
|
|
||||||
{
|
|
||||||
u32 result = x;
|
|
||||||
__asm__("rorl %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u64 rol64(u64 x, u64 n)
|
|
||||||
{
|
|
||||||
u64 result = x;
|
|
||||||
__asm__("rolq %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u64 ror64(u64 x, u64 n)
|
|
||||||
{
|
|
||||||
u64 result = x;
|
|
||||||
__asm__("rorq %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u64 umulh64(u64 a, u64 b)
|
|
||||||
{
|
|
||||||
u64 result;
|
|
||||||
__asm__("mulq %[b]" : "=d" (result) : [a] "a" (a), [b] "rm" (b));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline s64 mulh64(s64 a, s64 b)
|
|
||||||
{
|
|
||||||
s64 result;
|
|
||||||
__asm__("imulq %[b]" : "=d" (result) : [a] "a" (a), [b] "rm" (b));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
inline u8 rol8(u8 x, u8 n) { return _rotl8(x, n); }
|
|
||||||
inline u8 ror8(u8 x, u8 n) { return _rotr8(x, n); }
|
|
||||||
inline u16 rol16(u16 x, u16 n) { return _rotl16(x, (u8)n); }
|
|
||||||
inline u16 ror16(u16 x, u16 n) { return _rotr16(x, (u8)n); }
|
|
||||||
inline u32 rol32(u32 x, u32 n) { return _rotl(x, (int)n); }
|
|
||||||
inline u32 ror32(u32 x, u32 n) { return _rotr(x, (int)n); }
|
|
||||||
inline u64 rol64(u64 x, u64 n) { return _rotl64(x, (int)n); }
|
|
||||||
inline u64 ror64(u64 x, u64 n) { return _rotr64(x, (int)n); }
|
|
||||||
inline u64 umulh64(u64 x, u64 y) { return __umulh(x, y); }
|
|
||||||
inline s64 mulh64(s64 x, s64 y) { return __mulh(x, y); }
|
|
||||||
#endif
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
|
|
||||||
#include "Emu/Cell/PPUOpcodes.h"
|
|
||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
#include "Emu/RSX/GSRender.h"
|
#include "Emu/RSX/GSRender.h"
|
||||||
#include "cellGcmSys.h"
|
#include "cellGcmSys.h"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
#include "Emu/Cell/SPUThread.h"
|
#include "Emu/Cell/SPUThread.h"
|
||||||
#include "Emu/Cell/lv2/sys_lwmutex.h"
|
#include "Emu/Cell/lv2/sys_lwmutex.h"
|
||||||
#include "Emu/Cell/lv2/sys_lwcond.h"
|
#include "Emu/Cell/lv2/sys_lwcond.h"
|
||||||
@ -2126,7 +2126,7 @@ s32 _spurs::add_workload(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<vo
|
|||||||
const u32 wmax = spurs->flags1 & SF1_32_WORKLOADS ? 0x20u : 0x10u; // TODO: check if can be changed
|
const u32 wmax = spurs->flags1 & SF1_32_WORKLOADS ? 0x20u : 0x10u; // TODO: check if can be changed
|
||||||
spurs->wklEnabled.atomic_op([spurs, wmax, &wnum](be_t<u32>& value)
|
spurs->wklEnabled.atomic_op([spurs, wmax, &wnum](be_t<u32>& value)
|
||||||
{
|
{
|
||||||
wnum = cntlz32(~(u32)value); // found empty position
|
wnum = utils::cntlz32(~(u32)value); // found empty position
|
||||||
if (wnum < wmax)
|
if (wnum < wmax)
|
||||||
{
|
{
|
||||||
value |= (u32)(0x80000000ull >> wnum); // set workload bit
|
value |= (u32)(0x80000000ull >> wnum); // set workload bit
|
||||||
@ -2249,7 +2249,7 @@ s32 _spurs::add_workload(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<vo
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
k |= 0x80000000 >> current->uniqueId;
|
k |= 0x80000000 >> current->uniqueId;
|
||||||
res_wkl = cntlz32(~k);
|
res_wkl = utils::cntlz32(~k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
#include "Emu/Cell/lv2/sys_event.h"
|
#include "Emu/Cell/lv2/sys_event.h"
|
||||||
#include "Emu/Cell/lv2/sys_process.h"
|
#include "Emu/Cell/lv2/sys_process.h"
|
||||||
#include "cellSync.h"
|
#include "cellSync.h"
|
||||||
@ -966,7 +966,7 @@ error_code _cellSyncLFQueueCompletePushPointer(ppu_thread& ppu, vm::ptr<CellSync
|
|||||||
{
|
{
|
||||||
var9_ = 1 << var9_;
|
var9_ = 1 << var9_;
|
||||||
}
|
}
|
||||||
s32 var9 = cntlz32((u32)(u16)~(var9_ | (u16)push3.m_h6)) - 16; // count leading zeros in u16
|
s32 var9 = utils::cntlz32((u32)(u16)~(var9_ | (u16)push3.m_h6)) - 16; // count leading zeros in u16
|
||||||
|
|
||||||
s32 var5 = (s32)(u16)push3.m_h6 | var9_;
|
s32 var5 = (s32)(u16)push3.m_h6 | var9_;
|
||||||
if (var9 & 0x30)
|
if (var9 & 0x30)
|
||||||
@ -1262,7 +1262,7 @@ error_code _cellSyncLFQueueCompletePopPointer(ppu_thread& ppu, vm::ptr<CellSyncL
|
|||||||
{
|
{
|
||||||
var9_ = 1 << var9_;
|
var9_ = 1 << var9_;
|
||||||
}
|
}
|
||||||
s32 var9 = cntlz32((u32)(u16)~(var9_ | (u16)pop3.m_h2)) - 16; // count leading zeros in u16
|
s32 var9 = utils::cntlz32((u32)(u16)~(var9_ | (u16)pop3.m_h2)) - 16; // count leading zeros in u16
|
||||||
|
|
||||||
s32 var5 = (s32)(u16)pop3.m_h2 | var9_;
|
s32 var5 = (s32)(u16)pop3.m_h2 | var9_;
|
||||||
if (var9 & 0x30)
|
if (var9 & 0x30)
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
#include "Emu/Cell/PPUOpcodes.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LOG_CHANNEL(sys_libc);
|
LOG_CHANNEL(sys_libc);
|
||||||
|
|
||||||
|
@ -4,10 +4,8 @@
|
|||||||
#include "PPUAnalyser.h"
|
#include "PPUAnalyser.h"
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "yaml-cpp/yaml.h"
|
#include "yaml-cpp/yaml.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
|
|
||||||
|
|
||||||
const ppu_decoder<ppu_itype> s_ppu_itype;
|
const ppu_decoder<ppu_itype> s_ppu_itype;
|
||||||
|
|
||||||
@ -2051,7 +2049,7 @@ void ppu_acontext::MULLI(ppu_opcode_t op)
|
|||||||
max = amax * op.simm16;
|
max = amax * op.simm16;
|
||||||
|
|
||||||
// Check overflow
|
// Check overflow
|
||||||
if (min >> 63 != ::mulh64(amin, op.simm16) || max >> 63 != ::mulh64(amax, op.simm16))
|
if (min >> 63 != utils::mulh64(amin, op.simm16) || max >> 63 != utils::mulh64(amax, op.simm16))
|
||||||
{
|
{
|
||||||
min = 0;
|
min = 0;
|
||||||
max = -1;
|
max = -1;
|
||||||
@ -2062,7 +2060,7 @@ void ppu_acontext::MULLI(ppu_opcode_t op)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr[op.rd] = spec_gpr::range(min, max, gpr[op.ra].tz() + ::cnttz64(op.simm16));
|
gpr[op.rd] = spec_gpr::range(min, max, gpr[op.ra].tz() + utils::cnttz64(op.simm16));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppu_acontext::SUBFIC(ppu_opcode_t op)
|
void ppu_acontext::SUBFIC(ppu_opcode_t op)
|
||||||
@ -2163,14 +2161,14 @@ void ppu_acontext::RLWIMI(ppu_opcode_t op)
|
|||||||
if (op.mb32 <= op.me32)
|
if (op.mb32 <= op.me32)
|
||||||
{
|
{
|
||||||
// 32-bit op, including mnemonics: INSLWI, INSRWI (TODO)
|
// 32-bit op, including mnemonics: INSLWI, INSRWI (TODO)
|
||||||
min = ::rol32((u32)min, op.sh32) & mask;
|
min = utils::rol32((u32)min, op.sh32) & mask;
|
||||||
max = ::rol32((u32)max, op.sh32) & mask;
|
max = utils::rol32((u32)max, op.sh32) & mask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Full 64-bit op with duplication
|
// Full 64-bit op with duplication
|
||||||
min = ::rol64((u32)min | min << 32, op.sh32) & mask;
|
min = utils::rol64((u32)min | min << 32, op.sh32) & mask;
|
||||||
max = ::rol64((u32)max | max << 32, op.sh32) & mask;
|
max = utils::rol64((u32)max | max << 32, op.sh32) & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask != -1)
|
if (mask != -1)
|
||||||
@ -2219,14 +2217,14 @@ void ppu_acontext::RLWINM(ppu_opcode_t op)
|
|||||||
// EXTRWI and other possible mnemonics
|
// EXTRWI and other possible mnemonics
|
||||||
}
|
}
|
||||||
|
|
||||||
min = ::rol32((u32)min, op.sh32) & mask;
|
min = utils::rol32((u32)min, op.sh32) & mask;
|
||||||
max = ::rol32((u32)max, op.sh32) & mask;
|
max = utils::rol32((u32)max, op.sh32) & mask;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Full 64-bit op with duplication
|
// Full 64-bit op with duplication
|
||||||
min = ::rol64((u32)min | min << 32, op.sh32) & mask;
|
min = utils::rol64((u32)min | min << 32, op.sh32) & mask;
|
||||||
max = ::rol64((u32)max | max << 32, op.sh32) & mask;
|
max = utils::rol64((u32)max | max << 32, op.sh32) & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpr[op.ra] = spec_gpr::approx(min, max);
|
gpr[op.ra] = spec_gpr::approx(min, max);
|
||||||
@ -2314,8 +2312,8 @@ void ppu_acontext::RLDICL(ppu_opcode_t op)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
min = ::rol64(min, sh) & mask;
|
min = utils::rol64(min, sh) & mask;
|
||||||
max = ::rol64(max, sh) & mask;
|
max = utils::rol64(max, sh) & mask;
|
||||||
gpr[op.ra] = spec_gpr::approx(min, max);
|
gpr[op.ra] = spec_gpr::approx(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2343,8 +2341,8 @@ void ppu_acontext::RLDICR(ppu_opcode_t op)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
min = ::rol64(min, sh) & mask;
|
min = utils::rol64(min, sh) & mask;
|
||||||
max = ::rol64(max, sh) & mask;
|
max = utils::rol64(max, sh) & mask;
|
||||||
gpr[op.ra] = spec_gpr::approx(min, max);
|
gpr[op.ra] = spec_gpr::approx(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2369,8 +2367,8 @@ void ppu_acontext::RLDIC(ppu_opcode_t op)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
min = ::rol64(min, sh) & mask;
|
min = utils::rol64(min, sh) & mask;
|
||||||
max = ::rol64(max, sh) & mask;
|
max = utils::rol64(max, sh) & mask;
|
||||||
gpr[op.ra] = spec_gpr::approx(min, max);
|
gpr[op.ra] = spec_gpr::approx(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2392,8 +2390,8 @@ void ppu_acontext::RLDIMI(ppu_opcode_t op)
|
|||||||
// INSRDI mnemonic
|
// INSRDI mnemonic
|
||||||
}
|
}
|
||||||
|
|
||||||
min = ::rol64(min, sh) & mask;
|
min = utils::rol64(min, sh) & mask;
|
||||||
max = ::rol64(max, sh) & mask;
|
max = utils::rol64(max, sh) & mask;
|
||||||
|
|
||||||
if (mask != -1)
|
if (mask != -1)
|
||||||
{
|
{
|
||||||
|
@ -1006,7 +1006,7 @@ struct ppu_acontext
|
|||||||
// Return number of trailing zero bits
|
// Return number of trailing zero bits
|
||||||
u64 tz() const
|
u64 tz() const
|
||||||
{
|
{
|
||||||
return ::cnttz64(mask());
|
return utils::cnttz64(mask());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Range NOT
|
// Range NOT
|
||||||
@ -1255,7 +1255,7 @@ struct ppu_acontext
|
|||||||
if (min < max)
|
if (min < max)
|
||||||
{
|
{
|
||||||
// Inverted constant MSB mask
|
// Inverted constant MSB mask
|
||||||
const u64 mix = ~0ull >> ::cntlz64(min ^ max, true);
|
const u64 mix = ~0ull >> utils::cntlz64(min ^ max, true);
|
||||||
r.bmin |= min & ~mix;
|
r.bmin |= min & ~mix;
|
||||||
r.bmax &= max | mix;
|
r.bmax &= max | mix;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "PPUThread.h"
|
#include "PPUThread.h"
|
||||||
#include "PPUInterpreter.h"
|
#include "PPUInterpreter.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@ -1851,7 +1852,7 @@ bool ppu_interpreter::VRLB(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
|
|
||||||
for (uint i = 0; i < 16; i++)
|
for (uint i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
d._u8[i] = rol8(a._u8[i], b._u8[i]);
|
d._u8[i] = utils::rol8(a._u8[i], b._u8[i]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1864,7 +1865,7 @@ bool ppu_interpreter::VRLH(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
|
|
||||||
for (uint i = 0; i < 8; i++)
|
for (uint i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
d._u16[i] = rol16(a._u16[i], b._u8[i * 2] & 0xf);
|
d._u16[i] = utils::rol16(a._u16[i], b._u8[i * 2] & 0xf);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1877,7 +1878,7 @@ bool ppu_interpreter::VRLW(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
|
|
||||||
for (uint w = 0; w < 4; w++)
|
for (uint w = 0; w < 4; w++)
|
||||||
{
|
{
|
||||||
d._u32[w] = rol32(a._u32[w], b._u8[w * 4] & 0x1f);
|
d._u32[w] = utils::rol32(a._u32[w], b._u8[w * 4] & 0x1f);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3036,21 +3037,21 @@ bool ppu_interpreter::BCCTR(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
bool ppu_interpreter::RLWIMI(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLWIMI(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
const u64 mask = ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
const u64 mask = ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
||||||
ppu.gpr[op.ra] = (ppu.gpr[op.ra] & ~mask) | (dup32(rol32(u32(ppu.gpr[op.rs]), op.sh32)) & mask);
|
ppu.gpr[op.ra] = (ppu.gpr[op.ra] & ~mask) | (dup32(utils::rol32(u32(ppu.gpr[op.rs]), op.sh32)) & mask);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ppu_interpreter::RLWINM(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLWINM(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = dup32(rol32(u32(ppu.gpr[op.rs]), op.sh32)) & ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
ppu.gpr[op.ra] = dup32(utils::rol32(u32(ppu.gpr[op.rs]), op.sh32)) & ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ppu_interpreter::RLWNM(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLWNM(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = dup32(rol32(u32(ppu.gpr[op.rs]), ppu.gpr[op.rb] & 0x1f)) & ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
ppu.gpr[op.ra] = dup32(utils::rol32(u32(ppu.gpr[op.rs]), ppu.gpr[op.rb] & 0x1f)) & ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3095,21 +3096,21 @@ bool ppu_interpreter::ANDIS(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
|
|
||||||
bool ppu_interpreter::RLDICL(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLDICL(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = rol64(ppu.gpr[op.rs], op.sh64) & (~0ull >> op.mbe64);
|
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], op.sh64) & (~0ull >> op.mbe64);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ppu_interpreter::RLDICR(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLDICR(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = rol64(ppu.gpr[op.rs], op.sh64) & (~0ull << (op.mbe64 ^ 63));
|
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], op.sh64) & (~0ull << (op.mbe64 ^ 63));
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ppu_interpreter::RLDIC(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLDIC(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = rol64(ppu.gpr[op.rs], op.sh64) & ppu_rotate_mask(op.mbe64, op.sh64 ^ 63);
|
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], op.sh64) & ppu_rotate_mask(op.mbe64, op.sh64 ^ 63);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3117,21 +3118,21 @@ bool ppu_interpreter::RLDIC(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
bool ppu_interpreter::RLDIMI(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLDIMI(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
const u64 mask = ppu_rotate_mask(op.mbe64, op.sh64 ^ 63);
|
const u64 mask = ppu_rotate_mask(op.mbe64, op.sh64 ^ 63);
|
||||||
ppu.gpr[op.ra] = (ppu.gpr[op.ra] & ~mask) | (rol64(ppu.gpr[op.rs], op.sh64) & mask);
|
ppu.gpr[op.ra] = (ppu.gpr[op.ra] & ~mask) | (utils::rol64(ppu.gpr[op.rs], op.sh64) & mask);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ppu_interpreter::RLDCL(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLDCL(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = rol64(ppu.gpr[op.rs], ppu.gpr[op.rb] & 0x3f) & (~0ull >> op.mbe64);
|
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], ppu.gpr[op.rb] & 0x3f) & (~0ull >> op.mbe64);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ppu_interpreter::RLDCR(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::RLDCR(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = rol64(ppu.gpr[op.rs], ppu.gpr[op.rb] & 0x3f) & (~0ull << (op.mbe64 ^ 63));
|
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], ppu.gpr[op.rb] & 0x3f) & (~0ull << (op.mbe64 ^ 63));
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3194,7 +3195,7 @@ bool ppu_interpreter::SUBFC(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
|
|
||||||
bool ppu_interpreter::MULHDU(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::MULHDU(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.rd] = umulh64(ppu.gpr[op.ra], ppu.gpr[op.rb]);
|
ppu.gpr[op.rd] = utils::umulh64(ppu.gpr[op.ra], ppu.gpr[op.rb]);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3225,7 +3226,7 @@ bool ppu_interpreter::MFOCRF(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
if (op.l11)
|
if (op.l11)
|
||||||
{
|
{
|
||||||
// MFOCRF
|
// MFOCRF
|
||||||
const u32 n = cntlz32(op.crm) & 7;
|
const u32 n = utils::cntlz32(op.crm) & 7;
|
||||||
const u32 p = n * 4;
|
const u32 p = n * 4;
|
||||||
const u32 v = ppu.cr[p + 0] << 3 | ppu.cr[p + 1] << 2 | ppu.cr[p + 2] << 1 | ppu.cr[p + 3] << 0;
|
const u32 v = ppu.cr[p + 0] << 3 | ppu.cr[p + 1] << 2 | ppu.cr[p + 2] << 1 | ppu.cr[p + 3] << 0;
|
||||||
|
|
||||||
@ -3274,7 +3275,7 @@ bool ppu_interpreter::SLW(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
|
|
||||||
bool ppu_interpreter::CNTLZW(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::CNTLZW(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = cntlz32(u32(ppu.gpr[op.rs]));
|
ppu.gpr[op.ra] = utils::cntlz32(u32(ppu.gpr[op.rs]));
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3354,7 +3355,7 @@ bool ppu_interpreter::LWZUX(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
|
|
||||||
bool ppu_interpreter::CNTLZD(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::CNTLZD(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.ra] = cntlz64(ppu.gpr[op.rs]);
|
ppu.gpr[op.ra] = utils::cntlz64(ppu.gpr[op.rs]);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3392,7 +3393,7 @@ bool ppu_interpreter::LVEWX(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
|
|
||||||
bool ppu_interpreter::MULHD(ppu_thread& ppu, ppu_opcode_t op)
|
bool ppu_interpreter::MULHD(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
ppu.gpr[op.rd] = mulh64(ppu.gpr[op.ra], ppu.gpr[op.rb]);
|
ppu.gpr[op.rd] = utils::mulh64(ppu.gpr[op.ra], ppu.gpr[op.rb]);
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3516,7 +3517,7 @@ bool ppu_interpreter::MTOCRF(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
{
|
{
|
||||||
// MTOCRF
|
// MTOCRF
|
||||||
|
|
||||||
const u32 n = cntlz32(op.crm) & 7;
|
const u32 n = utils::cntlz32(op.crm) & 7;
|
||||||
const u32 p = n * 4;
|
const u32 p = n * 4;
|
||||||
const u64 v = (s >> (p ^ 0x1c)) & 0xf;
|
const u64 v = (s >> (p ^ 0x1c)) & 0xf;
|
||||||
*(u32*)(u8*)(ppu.cr + p) = *(u32*)(s_table + v);
|
*(u32*)(u8*)(ppu.cr + p) = *(u32*)(s_table + v);
|
||||||
@ -3641,7 +3642,7 @@ bool ppu_interpreter::MULLD(ppu_thread& ppu, ppu_opcode_t op)
|
|||||||
ppu.gpr[op.rd] = (s64)(RA * RB);
|
ppu.gpr[op.rd] = (s64)(RA * RB);
|
||||||
if (UNLIKELY(op.oe))
|
if (UNLIKELY(op.oe))
|
||||||
{
|
{
|
||||||
const s64 high = mulh64(RA, RB);
|
const s64 high = utils::mulh64(RA, RB);
|
||||||
ppu_ov_set(ppu, high != s64(ppu.gpr[op.rd]) >> 63);
|
ppu_ov_set(ppu, high != s64(ppu.gpr[op.rd]) >> 63);
|
||||||
}
|
}
|
||||||
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
if (UNLIKELY(op.rc)) ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.rd], 0);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../../Utilities/BitField.h"
|
#include "Utilities/BitField.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
|
|
||||||
template<typename T, u32 I, u32 N> using ppu_bf_t = bf_t<T, sizeof(T) * 8 - N - I, N>;
|
template<typename T, u32 I, u32 N> using ppu_bf_t = bf_t<T, sizeof(T) * 8 - N - I, N>;
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ union ppu_opcode_t
|
|||||||
|
|
||||||
inline u64 ppu_rotate_mask(u32 mb, u32 me)
|
inline u64 ppu_rotate_mask(u32 mb, u32 me)
|
||||||
{
|
{
|
||||||
return ror64(~0ull << (63 ^ (me - mb)), mb);
|
return utils::ror64(~0ull << (63 ^ (me - mb)), mb);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u32 ppu_decode(u32 inst)
|
inline u32 ppu_decode(u32 inst)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "SPUThread.h"
|
#include "SPUThread.h"
|
||||||
#include "SPUInterpreter.h"
|
#include "SPUInterpreter.h"
|
||||||
#include "Utilities/sysinfo.h"
|
#include "Utilities/sysinfo.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
#include "PPUAnalyser.h"
|
#include "PPUAnalyser.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -630,7 +631,7 @@ spu_function_t spu_recompiler::compile(std::vector<u32>&& func_rv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine which value will be duplicated at hole positions
|
// Determine which value will be duplicated at hole positions
|
||||||
const u32 w3 = func.at((j - start + ~::cntlz32(cmask, true) % 4 * 4) / 4 + 1);
|
const u32 w3 = func.at((j - start + ~utils::cntlz32(cmask, true) % 4 * 4) / 4 + 1);
|
||||||
words.push_back(cmask & 1 ? func[(j - start + 0) / 4 + 1] : w3);
|
words.push_back(cmask & 1 ? func[(j - start + 0) / 4 + 1] : w3);
|
||||||
words.push_back(cmask & 2 ? func[(j - start + 4) / 4 + 1] : w3);
|
words.push_back(cmask & 2 ? func[(j - start + 4) / 4 + 1] : w3);
|
||||||
words.push_back(cmask & 4 ? func[(j - start + 8) / 4 + 1] : w3);
|
words.push_back(cmask & 4 ? func[(j - start + 8) / 4 + 1] : w3);
|
||||||
@ -3413,7 +3414,7 @@ void spu_recompiler::ROTQBYI(spu_opcode_t op)
|
|||||||
}
|
}
|
||||||
else if (s == 4 || s == 8 || s == 12)
|
else if (s == 4 || s == 8 || s == 12)
|
||||||
{
|
{
|
||||||
c->pshufd(va, va, ::rol8(0xE4, s / 2));
|
c->pshufd(va, va, utils::rol8(0xE4, s / 2));
|
||||||
}
|
}
|
||||||
else if (utils::has_ssse3())
|
else if (utils::has_ssse3())
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Utilities/JIT.h"
|
#include "Utilities/JIT.h"
|
||||||
#include "Utilities/sysinfo.h"
|
#include "Utilities/sysinfo.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
#include "SPUThread.h"
|
#include "SPUThread.h"
|
||||||
#include "SPUInterpreter.h"
|
#include "SPUInterpreter.h"
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ bool spu_interpreter::ROT(SPUThread& spu, spu_opcode_t op)
|
|||||||
|
|
||||||
for (u32 i = 0; i < 4; i++)
|
for (u32 i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
spu.gpr[op.rt]._u32[i] = rol32(a._u32[i], b._u32[i]);
|
spu.gpr[op.rt]._u32[i] = utils::rol32(a._u32[i], b._u32[i]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -260,7 +260,7 @@ bool spu_interpreter::ROTH(SPUThread& spu, spu_opcode_t op)
|
|||||||
|
|
||||||
for (u32 i = 0; i < 8; i++)
|
for (u32 i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
spu.gpr[op.rt]._u16[i] = rol16(a._u16[i], b._u16[i]);
|
spu.gpr[op.rt]._u16[i] = utils::rol16(a._u16[i], b._u16[i]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -855,7 +855,7 @@ bool spu_interpreter::CLZ(SPUThread& spu, spu_opcode_t op)
|
|||||||
{
|
{
|
||||||
for (u32 i = 0; i < 4; i++)
|
for (u32 i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
spu.gpr[op.rt]._u32[i] = cntlz32(spu.gpr[op.ra]._u32[i]);
|
spu.gpr[op.rt]._u32[i] = utils::cntlz32(spu.gpr[op.ra]._u32[i]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "Utilities/cond.h"
|
#include "Utilities/cond.h"
|
||||||
#include "Utilities/Thread.h"
|
#include "Utilities/Thread.h"
|
||||||
#include "Utilities/VirtualMemory.h"
|
#include "Utilities/VirtualMemory.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
#include "Emu/CPU/CPUThread.h"
|
#include "Emu/CPU/CPUThread.h"
|
||||||
#include "Emu/Cell/lv2/sys_memory.h"
|
#include "Emu/Cell/lv2/sys_memory.h"
|
||||||
#include "Emu/RSX/GSRender.h"
|
#include "Emu/RSX/GSRender.h"
|
||||||
@ -599,7 +600,7 @@ namespace vm
|
|||||||
const u32 size = ::align(orig_size, min_page_size);
|
const u32 size = ::align(orig_size, min_page_size);
|
||||||
|
|
||||||
// Check alignment (it's page allocation, so passing small values there is just silly)
|
// Check alignment (it's page allocation, so passing small values there is just silly)
|
||||||
if (align < min_page_size || align != (0x80000000u >> cntlz32(align, true)))
|
if (align < min_page_size || align != (0x80000000u >> utils::cntlz32(align, true)))
|
||||||
{
|
{
|
||||||
fmt::throw_exception("Invalid alignment (size=0x%x, align=0x%x)" HERE, size, align);
|
fmt::throw_exception("Invalid alignment (size=0x%x, align=0x%x)" HERE, size, align);
|
||||||
}
|
}
|
||||||
@ -852,7 +853,7 @@ namespace vm
|
|||||||
const u32 size = ::align(orig_size, 0x10000);
|
const u32 size = ::align(orig_size, 0x10000);
|
||||||
|
|
||||||
// Check alignment
|
// Check alignment
|
||||||
if (align < 0x10000 || align != (0x80000000u >> ::cntlz32(align, true)))
|
if (align < 0x10000 || align != (0x80000000u >> utils::cntlz32(align, true)))
|
||||||
{
|
{
|
||||||
fmt::throw_exception("Invalid alignment (size=0x%x, align=0x%x)" HERE, size, align);
|
fmt::throw_exception("Invalid alignment (size=0x%x, align=0x%x)" HERE, size, align);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "../System.h"
|
#include "../System.h"
|
||||||
#include "Utilities/geometry.h"
|
#include "Utilities/geometry.h"
|
||||||
|
#include "Utilities/asm.h"
|
||||||
#include "gcm_enums.h"
|
#include "gcm_enums.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -299,14 +300,14 @@ namespace rsx
|
|||||||
//
|
//
|
||||||
static inline u32 ceil_log2(u32 value)
|
static inline u32 ceil_log2(u32 value)
|
||||||
{
|
{
|
||||||
return value <= 1 ? 0 : ::cntlz32((value - 1) << 1, true) ^ 31;
|
return value <= 1 ? 0 : utils::cntlz32((value - 1) << 1, true) ^ 31;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 next_pow2(u32 x)
|
static inline u32 next_pow2(u32 x)
|
||||||
{
|
{
|
||||||
if (x <= 2) return x;
|
if (x <= 2) return x;
|
||||||
|
|
||||||
return static_cast<u32>((1ULL << 32) >> ::cntlz32(x - 1, true));
|
return static_cast<u32>((1ULL << 32) >> utils::cntlz32(x - 1, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns interleaved bits of X|Y|Z used as Z-order curve indices
|
// Returns interleaved bits of X|Y|Z used as Z-order curve indices
|
||||||
|
Loading…
x
Reference in New Issue
Block a user