From c745c2d2d3ca71829c859fe270b7b34899bba763 Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Tue, 16 Jan 2024 13:16:03 +0100 Subject: [PATCH] Improved scrolling and added better memcpy/memmove functions written in assembly. --- targets/_any/include/string.h | 4 +- targets/_any/src/cstdlib/string.cpp | 8 ++-- targets/_any/src/os/draw.cpp | 21 ++++++---- targets/x86_64/src/cstdlib/memory.s | 63 +++++++++++++++++++++++------ 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/targets/_any/include/string.h b/targets/_any/include/string.h index a786765..e01cd4e 100644 --- a/targets/_any/include/string.h +++ b/targets/_any/include/string.h @@ -11,8 +11,8 @@ BA_EXTERN_C_BEGIN BA_CXX_NODISCARD int memcmp(const void* lhs, const void* rhs, size_t count) BA_CXX_NOEXCEPT; -void memcpy(void* dest, const void* src, size_t count) BA_CXX_NOEXCEPT; -void memmove(void* dest, const void* src, size_t count) BA_CXX_NOEXCEPT; +void* memcpy(void* dest, const void* src, size_t count) BA_CXX_NOEXCEPT; +void* memmove(void* dest, const void* src, size_t count) BA_CXX_NOEXCEPT; void* memset(void* dest, int value, size_t count) BA_CXX_NOEXCEPT; BA_CXX_NODISCARD size_t strlen(const char* str) BA_CXX_NOEXCEPT; diff --git a/targets/_any/src/cstdlib/string.cpp b/targets/_any/src/cstdlib/string.cpp index 6ba9dcc..e6abf25 100644 --- a/targets/_any/src/cstdlib/string.cpp +++ b/targets/_any/src/cstdlib/string.cpp @@ -20,16 +20,16 @@ int memcmp(const void* lhs, const void* rhs, size_t count) noexcept } #if !defined(__x86_64__) -void memcpy(void* dest, const void* src, size_t count) noexcept +void* memcpy(void* dest, const void* src, size_t count) noexcept { for (size_t pos = 0; pos < count; ++pos) { *(static_cast(dest) + pos) = *(static_cast(src) + pos); } + return dest; } -#endif -void memmove(void* dest, const void* src, size_t count) noexcept +void* memmove(void* dest, const void* src, size_t count) noexcept { if (dest < src) { @@ -45,7 +45,9 @@ void memmove(void* dest, const void* src, size_t count) noexcept *(static_cast(dest) + count - pos - 1) = *(static_cast(src) + count - pos - 1); } } + return dest; } +#endif void* memset(void* dest, int value, size_t count) noexcept { diff --git a/targets/_any/src/os/draw.cpp b/targets/_any/src/os/draw.cpp index f6a1d9a..5454583 100644 --- a/targets/_any/src/os/draw.cpp +++ b/targets/_any/src/os/draw.cpp @@ -16,11 +16,16 @@ void scrollVertical(int scrollY, const Pixel& fillColor) noexcept if (scrollY == 0) { return; } - const std::ptrdiff_t pixelOffset = scrollY * gFramebuffer.getPitch(); + if (scrollY > 0) { - // std::memmove(gFramebuffer.getBase(), gFramebuffer.getBase() + pixelOffset, gFramebuffer.getBufferSize() - (4 * pixelOffset)); - // std::memset(gFramebuffer.getBase() + pixelOffset, 0, ) + const size_t bytesPerRow = gDoubleBuffer.getPitch() * sizeof(Pixel); + const size_t bytesToMove = (gDoubleBuffer.getHeight() - scrollY) * bytesPerRow; + const size_t byteDist = scrollY * bytesPerRow; + uint8_t* basePtr = reinterpret_cast(gDoubleBuffer.getBase()); + std::memmove(basePtr, basePtr + byteDist, bytesToMove); + std::memset(basePtr + byteDist, 0, byteDist); + std::memcpy(gFramebuffer.getBase(), gDoubleBuffer.getBase(), gDoubleBuffer.getHeight() * bytesPerRow); } } } @@ -108,11 +113,11 @@ void character(unsigned posX, unsigned posY, const psf::Font& font, char chr, co void scrollBy(int scrollX, int scrollY, const Pixel& fillColor) noexcept { - // if (scrollX == 0) - // { - // scrollVertical(scrollY, fillColor); - // return; - // } + if (scrollX == 0) + { + scrollVertical(scrollY, fillColor); + return; + } const int width = static_cast(gFramebuffer.getHeight()); const int height = static_cast(gFramebuffer.getHeight()); const bool reverseX = scrollX < 0; diff --git a/targets/x86_64/src/cstdlib/memory.s b/targets/x86_64/src/cstdlib/memory.s index 753676c..c4d9344 100644 --- a/targets/x86_64/src/cstdlib/memory.s +++ b/targets/x86_64/src/cstdlib/memory.s @@ -3,25 +3,64 @@ .global memcpy .type memcpy @function -// int memcpy(void* dest [%rdi], void* src [%rsi], size_t count [%rdx]) +// void* memcpy(void* dest [%rdi], void* src [%rsi], size_t count [%rdx]) // memcpy: - cmpq %rdx, 4 - jl memcpy_bytes - movq (%rsi), %rax - movq %rax, (%rdi) - addq $4, %rsi - addq $4, %rdi - subq $4, %rdx - jmp memcpy + movq %rdi, %rax // return value +memcpy_qwords: + cmpq $8, %rdx // check if the remaining bytes are at least 8 + jl memcpy_bytes // if not copy the remaining bytes per byte + movq (%rsi), %rcx // if yes, copy using movq + movq %rcx, (%rdi) + addq $8, %rsi + addq $8, %rdi + subq $8, %rdx + jmp memcpy_qwords memcpy_bytes: - cmpq %rdx, 0 + cmpq $0, %rdx je memcpy_end - movb (%rsi), %ah - movb %ah, (%rdi) + movb (%rsi), %ch + movb %ch, (%rdi) addq $1, %rsi addq $1, %rdi subq $1, %rdx jmp memcpy_bytes memcpy_end: ret + +.global memmove +.type memmove @function +// void* memmove(void* dest [%rdi], void* src [%rsi], size_t count [%rdx]) +// +memmove: + movq %rdi, %rax // preserve dest as return value + cmpq %rsi, %rdi // check if dest > src + jg memmove_backward // if yes, do everything backwards + movq %rsi, %rcx // check if (src - dest) < 8 + subq %rdi, %rcx + cmpq $8, %rdi + jl memcpy_bytes // if yes, we have to do a bytewise copy + jmp memcpy_qwords // otherwise copy whole qwords +memmove_backward: // dest > src, copy backwards + addq %rdx, %rdi // dest = dest + count + addq %rdx, %rsi // src = src + count +memmove_qwords: + cmpq $8, %rdx // check if the remaining bytes are at least 8 + jl memmove_bytes // if not copy the remaining bytes per byte + movq -8(%rsi), %rcx // if yes, copy using movq + movq %rcx, -8(%rdi) + subq $8, %rsi + subq $8, %rdi + subq $8, %rdx + jmp memmove_qwords +memmove_bytes: + cmpq $0, %rdx + je memmove_end + movb (%rsi), %ch + movb %ch, (%rdi) + subq $1, %rsi + subq $1, %rdi + subq $1, %rdx + jmp memmove_bytes +memmove_end: + ret