From 67ac8bf0706b4c8498d240fd790324d2acbd2d5a Mon Sep 17 00:00:00 2001 From: Wilfried Rabouin Date: Sat, 4 Mar 2017 14:41:40 +0100 Subject: [PATCH] PPUInterpreter: Fix undefined behavior of left rotate functions (#2469) * PPUInterpreter: Fix undefined behavior of rol8 and rol16 with inline assembly * PPUInterpreter: Fix undefined behavior of rol32 and rol64 * PPUInterpreter: Change left rotate functions to inline functions and move to types.h --- Utilities/types.h | 36 +++++++++++++++++++++++++++++++ rpcs3/Emu/Cell/PPUInterpreter.cpp | 5 ----- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Utilities/types.h b/Utilities/types.h index 275b1d4d2d..7a005a918d 100644 --- a/Utilities/types.h +++ b/Utilities/types.h @@ -904,3 +904,39 @@ inline void busy_wait(std::size_t count = 100) { while (count--) _mm_pause(); } + +// Left rotate helpers +#if defined(__GNUG__) +inline u8 rol8(const u8 x, const u8 n) +{ + u8 result = x; + __asm__("rolb %[n], %[result]" : [result] "+g" (result) : [n] "c" (n)); + return result; +} + +inline u16 rol16(const u16 x, const u16 n) +{ + u16 result = x; + __asm__("rolw %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n)); + return result; +} + +inline u32 rol32(const u32 x, const u32 n) +{ + u32 result = x; + __asm__("roll %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n)); + return result; +} + +inline u64 rol64(const u64 x, const u64 n) +{ + u64 result = x; + __asm__("rolq %b[n], %[result]" : [result] "+g" (result) : [n] "c" (n)); + return result; +} +#elif defined(_MSC_VER) +inline u8 rol8(const u8 x, const u8 n) { return _rotl8(x, n); } +inline u16 rol16(const u16 x, const u16 n) { return _rotl16(x, n); } +inline u32 rol32(const u32 x, const u32 n) { return _rotl(x, n); } +inline u64 rol64(const u64 x, const u64 n) { return _rotl64(x, n); } +#endif \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUInterpreter.cpp b/rpcs3/Emu/Cell/PPUInterpreter.cpp index 512a3cb5ef..7de9da31e2 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/PPUInterpreter.cpp @@ -5,11 +5,6 @@ #include -// TODO: fix rol8 and rol16 for __GNUG__ (probably with __asm__) -inline u8 rol8(const u8 x, const u8 n) { return x << n | x >> (8 - n); } -inline u16 rol16(const u16 x, const u16 n) { return x << n | x >> (16 - n); } -inline u32 rol32(const u32 x, const u32 n) { return x << n | x >> (32 - n); } -inline u64 rol64(const u64 x, const u64 n) { return x << n | x >> (64 - n); } inline u64 dup32(const u32 x) { return x | static_cast(x) << 32; } #if defined(__GNUG__)