OXYGENHUB
◆ main openmsx / src / utils / MemoryOps.cc
1.5 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "MemoryOps.hh"
2
3
#include "endian.hh"
4
5
#include <algorithm>
6
#include <bit>
7
#include <cassert>
8
#include <cstdlib>
9
#include <new>
10
11
#ifdef _WIN32
12
    #include <malloc.h>  // _aligned_malloc, _aligned_free
13
#endif
14
15
namespace openmsx::MemoryOps {
16
17
void fill_2(std::span<uint32_t> out, uint32_t val0, uint32_t val1)
18
{
19
	if (out.empty()) [[unlikely]] return;
20
21
	// Align at 64-bit boundary.
22
	if (std::bit_cast<uintptr_t>(out.data()) & alignof(uint32_t)) [[unlikely]] {
23
		out.front() = val1; // start at odd pixel
24
		out = out.subspan(1);
25
	}
26
27
	// Main loop: (aligned) 64-bit fill.
28
	std::span<uint64_t> out64{std::bit_cast<uint64_t*>(out.data()), out.size() / 2};
29
	uint64_t val64 = Endian::BIG ? (uint64_t(val0) << 32) | val1
30
	                             : val0 | (uint64_t(val1) << 32);
31
	std::ranges::fill(out64, val64);
32
33
	// Single remaining pixel.
34
	if (out.size() & 1) [[unlikely]] {
35
		out.back() = val0;
36
	}
37
}
38
39
40
void* mallocAligned(size_t alignment, size_t size)
41
{
42
	assert("must be a power of 2" && std::has_single_bit(alignment));
43
	assert(alignment >= sizeof(void*));
44
#ifdef _WIN32
45
	void* result = _aligned_malloc(size, alignment);
46
#else
47
	// Ensure size is a multiple of alignment for std::aligned_alloc()
48
	size = (size + alignment - 1) & ~(alignment - 1);
49
	void* result = std::aligned_alloc(alignment, size);
50
#endif
51
	if (!result && size) throw std::bad_alloc();
52
	return result;
53
}
54
55
void freeAligned(void* aligned)
56
{
57
#ifdef _WIN32
58
	_aligned_free(aligned);
59
#else
60
	std::free(aligned);
61
#endif
62
}
63
64
} // namespace openmsx::MemoryOps