diff --git a/Common/BitScan.h b/Common/BitScan.h
new file mode 100644
index 0000000000..729c320759
--- /dev/null
+++ b/Common/BitScan.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "ppsspp_config.h"
+
+#if PPSSPP_PLATFORM(WINDOWS)
+#include "Common/CommonWindows.h"
+
+// Use this if you know the value is non-zero.
+inline uint32_t clz32_nonzero(uint32_t value) {
+ DWORD index;
+ BitScanReverse(&index, value);
+ return 31 ^ (uint32_t)index;
+}
+
+inline uint32_t clz32(uint32_t value) {
+ if (!value)
+ return 32;
+ DWORD index;
+ BitScanReverse(&index, value);
+ return 31 ^ (uint32_t)index;
+}
+
+#else
+
+// Use this if you know the value is non-zero.
+inline uint32_t clz32_nonzero(uint32_t value) {
+ return __builtin_clz(value);
+}
+
+inline uint32_t clz32(uint32_t value) {
+ if (!value)
+ return 32;
+ return __builtin_clz(value);
+}
+
+#endif
diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index 226295fa38..7cd6bb9e56 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -128,7 +128,6 @@
-
@@ -384,6 +383,7 @@
+
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index bad1776855..68e7c01282 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -73,6 +73,7 @@
+
@@ -149,4 +150,4 @@
{c14d66ef-5f7c-4565-975a-72774e7ccfb9}
-
+
\ No newline at end of file
diff --git a/Core/MIPS/IR/IRInterpreter.cpp b/Core/MIPS/IR/IRInterpreter.cpp
index 51724a80ef..13753c78ac 100644
--- a/Core/MIPS/IR/IRInterpreter.cpp
+++ b/Core/MIPS/IR/IRInterpreter.cpp
@@ -4,6 +4,7 @@
#include "ppsspp_config.h"
#include "math/math_util.h"
#include "Common/Common.h"
+#include "Common/BitScan.h"
#ifdef _M_SSE
#include
@@ -563,14 +564,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) {
case IROp::Clz:
{
- int x = 31;
- int count = 0;
- int value = mips->r[inst->src1];
- while (x >= 0 && !(value & (1 << x))) {
- count++;
- x--;
- }
- mips->r[inst->dest] = count;
+ mips->r[inst->dest] = clz32(mips->r[inst->src1]);
break;
}
diff --git a/Core/MIPS/MIPSInt.cpp b/Core/MIPS/MIPSInt.cpp
index 0c29cccdae..903386a08e 100644
--- a/Core/MIPS/MIPSInt.cpp
+++ b/Core/MIPS/MIPSInt.cpp
@@ -15,13 +15,12 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
-// MIPS is really trivial :)
-
#include
#include "math/math_util.h"
#include "Common/Common.h"
+#include "Common/BitScan.h"
#include "Core/Config.h"
#include "Core/Core.h"
#include "Core/Host.h"
@@ -281,7 +280,6 @@ namespace MIPSInt
switch (op & 0x3f)
{
case 8: //jr
- // LOG(CPU,"returning from: %08x",PC);
DelayBranchTo(addr);
break;
case 9: //jalr
@@ -551,28 +549,10 @@ namespace MIPSInt
switch (op & 63)
{
case 22: //clz
- { //TODO: verify
- int x = 31;
- int count=0;
- while (x >= 0 && !(R(rs) & (1<= 0 && (R(rs) & (1<> 16) & 0xF) {
case 3:
{
@@ -363,6 +363,9 @@ namespace MIPSInt
case 7:
sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE);
break;
+ default:
+ _dbg_assert_msg_(CPU, 0, "Unknown matrix init op");
+ break;
}
ApplyPrefixST(&prefixed[off * 4], VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad);
WriteMatrix(prefixed, sz, vd);
@@ -1559,7 +1562,7 @@ namespace MIPSInt
int vd = _VD;
int vs = _VS;
int vt = _VT;
- int ins = (op >> 23) & 7;
+ int ins = (op >> 23) & 3;
VectorSize sz = (VectorSize)(ins + 1);
MatrixSize msz = (MatrixSize)(ins + 1);
@@ -1598,9 +1601,13 @@ namespace MIPSInt
VFPUConst constZ = n < 3 ? VFPUConst::ZERO : VFPUConst::NONE;
VFPUConst constW = n < 4 ? VFPUConst::ZERO : VFPUConst::NONE;
if (ins >= n) {
- constY = ins == 1 ? VFPUConst::ONE : VFPUConst::ZERO;
- constZ = ins == 2 ? VFPUConst::ONE : VFPUConst::ZERO;
- constW = ins == 3 ? VFPUConst::ONE : VFPUConst::ZERO;
+ if (ins == 1) {
+ constY = VFPUConst::ONE;
+ } else if (ins == 2) {
+ constZ = VFPUConst::ONE;
+ } else if (ins == 3) {
+ constW = VFPUConst::ONE;
+ }
}
u32 tprefixRemove = VFPU_SWIZZLE(0, n < 2 ? 3 : 0, n < 3 ? 3 : 0, n < 4 ? 3 : 0);
u32 tprefixAdd = VFPU_MAKE_CONSTANTS(constX, constY, constZ, constW);
diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp
index 46694c35a1..2a2ddcf27c 100644
--- a/Core/Screenshot.cpp
+++ b/Core/Screenshot.cpp
@@ -237,26 +237,24 @@ static bool ConvertPixelTo8888RGBA(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b
}
const u8 *ConvertBufferToScreenshot(const GPUDebugBuffer &buf, bool alpha, u8 *&temp, u32 &w, u32 &h) {
- int pixelSize = alpha ? 4 : 3;
+ size_t pixelSize = alpha ? 4 : 3;
GPUDebugBufferFormat nativeFmt = alpha ? GPU_DBG_FORMAT_8888 : GPU_DBG_FORMAT_888_RGB;
w = std::min(w, buf.GetStride());
h = std::min(h, buf.GetHeight());
// The temp buffer will be freed by the caller if set, and can be the return value.
- if (buf.GetFlipped() || buf.GetFormat() != nativeFmt) {
- temp = new u8[pixelSize * w * h];
- } else {
- temp = nullptr;
- }
+ temp = nullptr;
const u8 *buffer = buf.GetData();
if (buf.GetFlipped() && buf.GetFormat() == nativeFmt) {
+ temp = new u8[pixelSize * w * h];
// Silly OpenGL reads upside down, we flip to another buffer for simplicity.
for (u32 y = 0; y < h; y++) {
memcpy(temp + y * w * pixelSize, buffer + (buf.GetHeight() - y - 1) * buf.GetStride() * pixelSize, w * pixelSize);
}
} else if (buf.GetFormat() < GPU_DBG_FORMAT_FLOAT && buf.GetFormat() != nativeFmt) {
+ temp = new u8[pixelSize * w * h];
// Let's boil it down to how we need to interpret the bits.
int baseFmt = buf.GetFormat() & ~(GPU_DBG_FORMAT_REVERSE_FLAG | GPU_DBG_FORMAT_BRSWAP_FLAG);
bool rev = (buf.GetFormat() & GPU_DBG_FORMAT_REVERSE_FLAG) != 0;
@@ -284,6 +282,7 @@ const u8 *ConvertBufferToScreenshot(const GPUDebugBuffer &buf, bool alpha, u8 *&
}
}
} else if (buf.GetFormat() != nativeFmt) {
+ temp = new u8[pixelSize * w * h];
bool flip = buf.GetFlipped();
// This is pretty inefficient.
diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h
index 0f9410dc3f..e56a349df1 100644
--- a/GPU/Common/GPUDebugInterface.h
+++ b/GPU/Common/GPUDebugInterface.h
@@ -79,7 +79,7 @@ inline GPUDebugBufferFormat &operator |=(GPUDebugBufferFormat &lhs, const GPUDeb
}
struct GPUDebugBuffer {
- GPUDebugBuffer() : alloc_(false), data_(NULL) {
+ GPUDebugBuffer() {
}
GPUDebugBuffer(void *data, u32 stride, u32 height, GEBufferFormat fmt, bool reversed = false)
@@ -100,7 +100,7 @@ struct GPUDebugBuffer {
: alloc_(false), data_((u8 *)data), stride_(stride), height_(height), fmt_(fmt), flipped_(false) {
}
- GPUDebugBuffer(GPUDebugBuffer &&other) {
+ GPUDebugBuffer(GPUDebugBuffer &&other) noexcept {
alloc_ = other.alloc_;
data_ = other.data_;
height_ = other.height_;
@@ -108,14 +108,14 @@ struct GPUDebugBuffer {
flipped_ = other.flipped_;
fmt_ = other.fmt_;
other.alloc_ = false;
- other.data_ = NULL;
+ other.data_ = nullptr;
}
~GPUDebugBuffer() {
Free();
}
- GPUDebugBuffer &operator = (GPUDebugBuffer &&other) {
+ GPUDebugBuffer &operator = (GPUDebugBuffer &&other) noexcept {
if (this != &other) {
Free();
alloc_ = other.alloc_;
@@ -125,7 +125,7 @@ struct GPUDebugBuffer {
flipped_ = other.flipped_;
fmt_ = other.fmt_;
other.alloc_ = false;
- other.data_ = NULL;
+ other.data_ = nullptr;
}
return *this;
@@ -164,12 +164,12 @@ struct GPUDebugBuffer {
private:
u32 PixelSize(GPUDebugBufferFormat fmt) const;
- bool alloc_;
- u8 *data_;
- u32 stride_;
- u32 height_;
- GPUDebugBufferFormat fmt_;
- bool flipped_;
+ bool alloc_ = false;
+ u8 *data_ = nullptr;
+ u32 stride_ = 0;
+ u32 height_ = 0;
+ GPUDebugBufferFormat fmt_ = GPU_DBG_FORMAT_INVALID;
+ bool flipped_ = false;
};
struct GPUDebugVertex {
diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h
index 911ef1ab0b..17f0acb69a 100644
--- a/ext/native/thin3d/VulkanQueueRunner.h
+++ b/ext/native/thin3d/VulkanQueueRunner.h
@@ -246,8 +246,8 @@ private:
VulkanContext *vulkan_;
- VkFramebuffer backbuffer_;
- VkImage backbufferImage_;
+ VkFramebuffer backbuffer_ = VK_NULL_HANDLE;
+ VkImage backbufferImage_ = VK_NULL_HANDLE;
VkRenderPass backbufferRenderPass_ = VK_NULL_HANDLE;
VkRenderPass framebufferRenderPass_ = VK_NULL_HANDLE;
diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp
index ddf44c0ebb..444d3111bb 100644
--- a/ext/native/thin3d/VulkanRenderManager.cpp
+++ b/ext/native/thin3d/VulkanRenderManager.cpp
@@ -159,7 +159,7 @@ void VulkanRenderManager::CreateBackbuffers() {
VkCommandBuffer cmdInit = GetInitCmd();
for (uint32_t i = 0; i < swapchainImageCount_; i++) {
- SwapchainImageData sc_buffer;
+ SwapchainImageData sc_buffer{};
sc_buffer.image = swapchainImages[i];
VkImageViewCreateInfo color_image_view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
diff --git a/ext/native/thin3d/VulkanRenderManager.h b/ext/native/thin3d/VulkanRenderManager.h
index cfac32d75c..84f7cbeed2 100644
--- a/ext/native/thin3d/VulkanRenderManager.h
+++ b/ext/native/thin3d/VulkanRenderManager.h
@@ -288,8 +288,8 @@ private:
FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES];
// Submission time state
- int curWidth_;
- int curHeight_;
+ int curWidth_ = -1;
+ int curHeight_ = -1;
bool insideFrame_ = false;
VKRStep *curRenderStep_ = nullptr;
std::vector steps_;
@@ -310,7 +310,7 @@ private:
};
std::vector framebuffers_;
std::vector swapchainImages_;
- uint32_t swapchainImageCount_;
+ uint32_t swapchainImageCount_ = 0;
struct DepthBufferInfo {
VkFormat format = VK_FORMAT_UNDEFINED;
VkImage image = VK_NULL_HANDLE;
diff --git a/ext/native/ui/ui_screen.h b/ext/native/ui/ui_screen.h
index 99a6c486eb..c044e961a0 100644
--- a/ext/native/ui/ui_screen.h
+++ b/ext/native/ui/ui_screen.h
@@ -109,7 +109,7 @@ private:
class ListPopupScreen : public PopupScreen {
public:
- ListPopupScreen(std::string title) : PopupScreen(title), showButtons_(false) {}
+ ListPopupScreen(std::string title) : PopupScreen(title) {}
ListPopupScreen(std::string title, const std::vector &items, int selected, std::function callback, bool showButtons = false)
: PopupScreen(title, "OK", "Cancel"), adaptor_(items, selected), callback_(callback), showButtons_(showButtons) {
}
@@ -135,13 +135,13 @@ protected:
virtual bool ShowButtons() const override { return showButtons_; }
virtual void CreatePopupContents(UI::ViewGroup *parent) override;
UI::StringVectorListAdaptor adaptor_;
- UI::ListView *listView_;
+ UI::ListView *listView_ = nullptr;
private:
UI::EventReturn OnListChoice(UI::EventParams &e);
std::function callback_;
- bool showButtons_;
+ bool showButtons_ = false;
std::set hidden_;
};
@@ -169,7 +169,7 @@ namespace UI {
class SliderPopupScreen : public PopupScreen {
public:
SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title, int step = 1, const std::string &units = "")
- : PopupScreen(title, "OK", "Cancel"), units_(units), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {}
+ : PopupScreen(title, "OK", "Cancel"), units_(units), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {}
virtual void CreatePopupContents(ViewGroup *parent) override;
void SetNegativeDisable(const std::string &str) {
@@ -185,12 +185,12 @@ private:
EventReturn OnTextChange(EventParams ¶ms);
EventReturn OnSliderChange(EventParams ¶ms);
virtual void OnCompleted(DialogResult result) override;
- Slider *slider_;
- UI::TextEdit *edit_;
+ Slider *slider_ = nullptr;
+ UI::TextEdit *edit_ = nullptr;
std::string units_;
std::string negativeLabel_;
int *value_;
- int sliderValue_;
+ int sliderValue_ = 0;
int minValue_;
int maxValue_;
int step_;
diff --git a/ext/native/ui/view.h b/ext/native/ui/view.h
index 2ca22d1c38..45d0538d44 100644
--- a/ext/native/ui/view.h
+++ b/ext/native/ui/view.h
@@ -552,8 +552,8 @@ private:
float paddingLeft_;
float paddingRight_;
int step_;
- int repeat_;
- int repeatCode_;
+ int repeat_ = 0;
+ int repeatCode_ = 0;
};
class SliderFloat : public Clickable {
@@ -580,7 +580,7 @@ private:
float paddingLeft_;
float paddingRight_;
int repeat_;
- int repeatCode_;
+ int repeatCode_ = 0;
};
// Basic button that modifies a bitfield based on the pressed status. Supports multitouch.
diff --git a/ext/native/util/text/wrap_text.h b/ext/native/util/text/wrap_text.h
index 7418a8022e..61049bccef 100644
--- a/ext/native/util/text/wrap_text.h
+++ b/ext/native/util/text/wrap_text.h
@@ -31,7 +31,7 @@ protected:
// Position the current word starts at.
float x_ = 0.0f;
// Most recent width of word since last index.
- float wordWidth_;
+ float wordWidth_ = 0.0f;
// Force the next word to cut partially and wrap.
bool forceEarlyWrap_ = false;
};
diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp
index 9fdf32f8cd..b07feb5bb2 100644
--- a/unittest/UnitTest.cpp
+++ b/unittest/UnitTest.cpp
@@ -31,6 +31,9 @@
#include
#include
+#include "Common/BitScan.h"
+#include "Core/MIPS/MIPSVFPUUtils.h"
+
#include "base/NativeApp.h"
#include "base/logging.h"
#include "input/input_state.h"
@@ -459,6 +462,29 @@ bool TestQuickTexHash() {
return true;
}
+bool TestCLZ() {
+ static const uint32_t input[] = {
+ 0xFFFFFFFF,
+ 0x00FFFFF0,
+ 0x00101000,
+ 0x00003000,
+ 0x00000001,
+ 0x00000000,
+ };
+ static const uint32_t expected[] = {
+ 0,
+ 8,
+ 11,
+ 18,
+ 31,
+ 32,
+ };
+ for (int i = 0; i < ARRAY_SIZE(input); i++) {
+ EXPECT_EQ_INT(clz32(input[i]), expected[i]);
+ }
+ return true;
+}
+
typedef bool (*TestFunc)();
struct TestItem {
const char *name;
@@ -491,6 +517,7 @@ TestItem availableTests[] = {
TEST_ITEM(MatrixTranspose),
TEST_ITEM(ParseLBN),
TEST_ITEM(QuickTexHash),
+ TEST_ITEM(CLZ),
};
int main(int argc, const char *argv[]) {