summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-07-30 00:08:41 +0200
committerEugen Wissner <belka@caraus.de>2017-07-30 00:08:41 +0200
commit40e43c14657b58cced174f099b0ba2d0cfdb3532 (patch)
treeb756f3a5054e73237c839262601a5a7e2fd0fcab
parent5d145f524cd04ea657def5338d5cb9f2c7182a23 (diff)
downloadtanya-40e43c14657b58cced174f099b0ba2d0cfdb3532.tar.gz
Add memory.op.copy
-rw-r--r--.travis.yml3
-rw-r--r--source/tanya/memory/arch/x86_64.d13
-rw-r--r--source/tanya/memory/op.d115
3 files changed, 123 insertions, 8 deletions
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);
+ }
+}