diff --git a/.travis.yml b/.travis.yml index 20f9f23..7d8b844 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,9 +30,6 @@ before_script: script: - dub test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC - - if [ "$UNITTEST" = "unittest-cov" -a "$ARCH" = "x86_64" -a "$TRAVIS_OS_NAME" = "linux" ]; then - dub fetch dscanner && dub run dscanner -- -Isource --styleCheck; - fi after_success: - test "$UNITTEST" = "unittest-cov" && bash <(curl -s https://codecov.io/bash) diff --git a/source/tanya/memory/arch/x86_64.d b/source/tanya/memory/arch/x86_64.d index 02fe9c4..bd5f5a1 100644 --- a/source/tanya/memory/arch/x86_64.d +++ b/source/tanya/memory/arch/x86_64.d @@ -3,6 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* + * Implementions of functions found in $(D_PSYMBOL tanya.memory.op) for X86-64. + * * Copyright: Eugene Wissner 2017. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). @@ -12,17 +14,18 @@ module tanya.memory.arch.x86_64; version (D_InlineAsm_X86_64): -package void copy(const void[] src, void[] dst) +pragma(inline, true) +package (tanya.memory) void copy(const void[] source, void[] target) pure nothrow @system @nogc { asm pure nothrow @nogc { naked; - // RDX - src length. - // RCX - src data. - // RDI - dst length. - // RSI - dst data. + // RDX - source length. + // RCX - source data. + // RDI - target length. + // RSI - target data. // RDI and RSI should be preserved. mov RAX, RDI; diff --git a/source/tanya/memory/op.d b/source/tanya/memory/op.d new file mode 100644 index 0000000..98e5b90 --- /dev/null +++ b/source/tanya/memory/op.d @@ -0,0 +1,115 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Set of operations on memory blocks. + * + * Copyright: Eugene Wissner 2017. + * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, + * Mozilla Public License, v. 2.0). + * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) + */ +module tanya.memory.op; + +version (D_InlineAsm_X86_64) +{ + static import tanya.memory.arch.x86_64; +} + +/** + * Copies $(D_PARAM source) into $(D_PARAM target). + * + * $(D_PARAM source) and $(D_PARAM target) shall not overlap so that an element + * of $(D_PARAM target) points to an element of $(D_PARAM source). + * + * $(D_PARAM target) shall have enough space $(D_INLINECODE source.length) + * elements. + * + * Params: + * source = Memory to copy from. + * target = Destination memory. + * + * Precondition: $(D_INLINECODE source.length <= target.length). + */ +void copy(const void[] source, void[] target) pure nothrow @trusted @nogc +in +{ + assert(source.length <= target.length); +} +body +{ + version (D_InlineAsm_X86_64) + { + tanya.memory.arch.x86_64.copy(source, target); + } + else // Naive implementation. + { + auto source1 = cast(const(ubyte)*) source; + auto target1 = cast(ubyte*) target; + auto count = source.length; + enum alignmentMask = size_t.sizeof - 1; + + // Check if the pointers are aligned or at least can be aligned + // properly. + ushort naligned = (cast(size_t) source.ptr) & alignmentMask; + if (naligned == ((cast(size_t) target.ptr) & alignmentMask)) + { + // Align the pointers if possible. + if (naligned != 0) + { + count -= naligned; + while (naligned--) + { + *target1++ = *source1++; + } + } + // Copy size_t.sizeof bytes at once. + auto longSource = cast(const(size_t)*) source1; + auto longTarget = cast(size_t*) target1; + for (; count >= size_t.sizeof; count -= size_t.sizeof) + { + *longTarget++ = *longSource++; + } + // Adjust the original pointers. + source1 = cast(const(ubyte)*) longSource; + target1 = cast(ubyte*) longTarget; + } + // Copy the remaining bytes by one. + while (count--) + { + *target1++ = *source1++; + } + } +} + +/// +pure nothrow @safe @nogc unittest +{ + { + ubyte[9] source = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + ubyte[9] target; + source.copy(target); + assert(source == target); + } +} + +private pure nothrow @safe @nogc unittest +{ + { + ubyte[0] source, target; + source.copy(target); + } + { + ubyte[1] source = [1]; + ubyte[1] target; + source.copy(target); + assert(target[0] == 1); + } + { + ubyte[8] source = [1, 2, 3, 4, 5, 6, 7, 8]; + ubyte[8] target; + source.copy(target); + assert(source == target); + } +}