diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/tanya/memory/arch/x86_64.d | 346 | ||||
| -rw-r--r-- | source/tanya/memory/op.d | 43 |
2 files changed, 26 insertions, 363 deletions
diff --git a/source/tanya/memory/arch/x86_64.d b/source/tanya/memory/arch/x86_64.d deleted file mode 100644 index 57e1563..0000000 --- a/source/tanya/memory/arch/x86_64.d +++ /dev/null @@ -1,346 +0,0 @@ -/* 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/. */ - -/* - * Implementions of functions found in $(D_PSYMBOL tanya.memory.op) for x64. - * - * 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) - * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/memory/arch/x86_64.d, - * tanya/memory/arch/x86_64.d) - */ -module tanya.memory.arch.x86_64; - -import tanya.memory.op; - -version (D_InlineAsm_X86_64): - -pragma(inline, true) -package (tanya.memory) void copy(const void[] source, void[] target) -pure nothrow @system @nogc -{ - asm pure nothrow @nogc - { - naked; - - // RDI and RSI should be preserved. - mov RAX, RDI; - mov R8, RSI; - - // RDX - source length. - // RCX - source data. - // RDI - target length - // RSI - target data. - - mov RDI, RSI; - mov RSI, RCX; - - cmp RDX, 0x08; - jc aligned_1; - test EDI, 0x07; - jz aligned_8; - - naligned: - movsb; - dec RDX; - test EDI, 0x07; - jnz naligned; - - aligned_8: - mov RCX, RDX; - shr RCX, 0x03; - rep; - movsq; - and EDX, 0x07; - jz end; - - aligned_1: - // Write the remaining bytes. - mov RCX, RDX; - rep; - movsb; - - end: // Restore registers. - mov RSI, R8; - mov RDI, RAX; - - ret; - } -} - -pragma(inline, true) -package (tanya.memory) void fill(void[], ulong) pure nothrow @system @nogc -{ - asm pure nothrow @nogc - { - naked; - - // Check for zero length. - test RSI, RSI; - jz end; - - /* - * RDX - pointer. - * RSI - length. - * RDI - value filled with a byte. - */ - mov RAX, RSI; - mov R8, RDX; - - movq XMM0, RDI; - movlhps XMM0, XMM0; - - // Check if the pointer is aligned to a 16-byte boundary. - and R8, -0x10; - - // Compute the number of misaligned bytes. - mov R9, RDX; - sub R9, R8; - - test R9, R9; - jz aligned; - - // Get the number of bytes to be written until we are aligned. - mov RCX, 0x10; - sub RCX, R9; - - mov R8, RDX; - - naligned: - mov [ R8 ], DIL; // Write a byte. - - // Advance the pointer. Decrease the total number of bytes - // and the misaligned ones. - inc R8; - dec RCX; - dec RAX; - - // Checks if we are aligned. - test RCX, RCX; - jnz naligned; - - aligned: - // Checks if we're done writing bytes. - test RAX, RAX; - jz end; - - // Write 1 byte at a time. - cmp RAX, 8; - jl aligned_1; - - // Write 8 bytes at a time. - cmp RAX, 16; - jl aligned_8; - - // Write 16 bytes at a time. - cmp RAX, 32; - jl aligned_16; - - // Write 32 bytes at a time. - cmp RAX, 64; - jl aligned_32; - - aligned_64: - movdqa [ R8 ], XMM0; - movdqa [ R8 + 16 ], XMM0; - movdqa [ R8 + 32 ], XMM0; - movdqa [ R8 + 48 ], XMM0; - - add R8, 64; - sub RAX, 64; - - cmp RAX, 64; - jge aligned_64; - - // Checks if we're done writing bytes. - test RAX, RAX; - jz end; - - // Write 1 byte at a time. - cmp RAX, 8; - jl aligned_1; - - // Write 8 bytes at a time. - cmp RAX, 16; - jl aligned_8; - - // Write 16 bytes at a time. - cmp RAX, 32; - jl aligned_16; - - aligned_32: - movdqa [ R8 ], XMM0; - movdqa [ R8 + 16 ], XMM0; - - add R8, 32; - sub RAX, 32; - - // Checks if we're done writing bytes. - test RAX, RAX; - jz end; - - // Write 1 byte at a time. - cmp RAX, 8; - jl aligned_1; - - // Write 8 bytes at a time. - cmp RAX, 16; - jl aligned_8; - - aligned_16: - movdqa [ R8 ], XMM0; - - add R8, 16; - sub RAX, 16; - - // Checks if we're done writing bytes. - test RAX, RAX; - jz end; - - // Write 1 byte at a time. - cmp RAX, 8; - jl aligned_1; - - aligned_8: - mov [ R8 ], RDI; - - add R8, 8; - sub RAX, 8; - - // Checks if we're done writing bytes. - test RAX, RAX; - jz end; - - aligned_1: - mov [ R8 ], DIL; - - inc R8; - dec RAX; - - test RAX, RAX; - jnz aligned_1; - - end: - ret; - } -} - -pragma(inline, true) -package (tanya.memory) void copyBackward(const void[] source, void[] target) -pure nothrow @system @nogc -{ - asm pure nothrow @nogc - { - naked; - - // Save the registers should be restored. - mov R8, RSI; - mov R9, RDI; - - // RDX - source length. - // RCX - source data. - // RDI - target length - // RSI - target data. - - lea RDI, [ RSI + RDX - 1 ]; - lea RSI, [ RCX + RDX - 1 ]; - mov RCX, RDX; - - std; // Set the direction flag. - - rep; - movsb; - - cld; // Clear the direction flag. - - // Restore registers. - mov RDI, R9; - mov RSI, R8; - - ret; - } -} - -pragma(inline, true) -package (tanya.memory) int cmp(const void[] r1, const void[] r2) -pure nothrow @system @nogc -{ - asm pure nothrow @nogc - { - naked; - - // RDI and RSI should be preserved. - mov R9, RDI; - mov R8, RSI; - - // RDX - r1 length. - // RCX - r1 data. - // RDI - r2 length - // RSI - r2 data. - - mov RSI, RCX; - mov RCX, RDI; - mov RDI, R8; - - // Compare the lengths. - cmp RDX, RCX; - jl less; - jg greater; - - // Check if we're aligned. - cmp RDX, 0x08; - jc aligned_1; - test EDI, 0x07; - jz aligned_8; - - naligned: - cmpsb; - jl less; - jg greater; - - dec RDX; - test EDI, 0x07; - jnz naligned; - - aligned_8: - mov RCX, RDX; - shr RCX, 0x03; - - repe; - cmpsq; - jl less; - jg greater; - - and EDX, 0x07; - jz equal; - - aligned_1: // Compare the remaining bytes. - mov RCX, RDX; - - repe; - cmpsb; - jl less; - jg greater; - - equal: - xor RAX, RAX; // Return 0. - jmp end; - - greater: - mov RAX, 1; - jmp end; - - less: - mov RAX, -1; - jmp end; - - end: // Restore registers. - mov RSI, R8; - mov RDI, R9; - - ret; - } -} diff --git a/source/tanya/memory/op.d b/source/tanya/memory/op.d index e3c9451..9af7fad 100644 --- a/source/tanya/memory/op.d +++ b/source/tanya/memory/op.d @@ -14,13 +14,22 @@ */ module tanya.memory.op; -version (TanyaPhobos) +version (TanyaNative) { - import core.stdc.string; + extern private void fillMemory(void[], size_t) pure nothrow @system @nogc; + + extern private void copyMemory(const void[], void[]) + pure nothrow @system @nogc; + + extern private void moveMemory(const void[], void[]) + pure nothrow @system @nogc; + + extern private int cmpMemory(const void[], const void[]) + pure nothrow @system @nogc; } else { - static import tanya.memory.arch.x86_64; + import core.stdc.string; } private enum alignMask = size_t.sizeof - 1; @@ -49,13 +58,13 @@ in } body { - version (TanyaPhobos) + version (TanyaNative) { - memcpy(target.ptr, source.ptr, source.length); + copyMemory(source, target); } else { - tanya.memory.arch.x86_64.copy(source, target); + memcpy(target.ptr, source.ptr, source.length); } } @@ -112,13 +121,13 @@ private template filledBytes(ubyte Byte, ubyte I = 0) */ void fill(ubyte c = 0)(void[] memory) @trusted { - version (TanyaPhobos) + version (TanyaNative) { - memset(memory.ptr, c, memory.length); + fillMemory(memory, filledBytes!c); } else { - tanya.memory.arch.x86_64.fill(memory, filledBytes!c); + memset(memory.ptr, c, memory.length); } } @@ -187,13 +196,13 @@ in } body { - version (TanyaPhobos) + version (TanyaNative) { - memmove(target.ptr, source.ptr, source.length); + moveMemory(source, target); } else { - tanya.memory.arch.x86_64.copyBackward(source, target); + memmove(target.ptr, source.ptr, source.length); } } @@ -235,7 +244,11 @@ private nothrow @safe @nogc unittest */ int cmp(const void[] r1, const void[] r2) pure nothrow @trusted @nogc { - version (TanyaPhobos) + version (TanyaNative) + { + return cmpMemory(r1, r2); + } + else { if (r1.length > r2.length) { @@ -243,10 +256,6 @@ int cmp(const void[] r1, const void[] r2) pure nothrow @trusted @nogc } return r1.length < r2.length ? -1 : memcmp(r1.ptr, r2.ptr, r1.length); } - else - { - return tanya.memory.arch.x86_64.cmp(r1, r2); - } } /// |
