Last active
August 6, 2022 09:58
-
-
Save iK4tsu/a2e4f20ba2259deb09a9e18b186783c9 to your computer and use it in GitHub Desktop.
setmem.d (improvements of https://gist.github.com/ljmf00/14cd73e84521191f88b2bdc010ee1899)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module setmem; | |
version(unittest) | |
{ | |
import std.range : repeat; | |
import std.algorithm : equal; | |
} | |
version (LDC) | |
{ | |
nothrow @nogc | |
{ | |
pragma(LDC_intrinsic, "llvm.memset.p0i8.i#") | |
private void llvm_memset(T)(void* dst, ubyte val, T len, bool volatile_ = false) | |
if (__traits(isIntegral, T)); | |
} | |
} | |
export void* _d_memset(size_t tsz: 1)(return scope void* dst, scope void* val, size_t sz) | |
{ | |
version (LDC) | |
{ | |
llvm_memset(dst, *cast(ubyte*) val, sz); | |
return dst; | |
} | |
else | |
{ | |
import core.stdc.string : memset; | |
return memset(dst, *(cast(int*) val), sz); | |
} | |
} | |
/// | |
unittest | |
{ | |
ubyte[10] buf; | |
ubyte val = 123; | |
_d_memset!1(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
export void* _d_memset(size_t tsz: 2)(return scope void* dst, scope void* val, size_t sz) | |
{ | |
version (D_InlineAsm_X86) | |
{ | |
asm @safe pure nothrow @nogc | |
{ | |
mov EDI,dst ; | |
mov EAX,val ; | |
mov ECX,sz ; | |
mov EDX,EDI ; | |
rep ; | |
stosw ; | |
mov EAX,EDX ; | |
} | |
} | |
else | |
{ | |
scope ushort* buf = cast(ushort*) dst; | |
while(sz--) *buf++ = *cast(ushort*) val; | |
return dst; | |
} | |
} | |
/// | |
unittest | |
{ | |
ushort[10] buf; | |
ushort val = 1234; | |
_d_memset!2(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
export void* _d_memset(size_t tsz: 4)(return scope void* dst, scope void* val, size_t sz) | |
{ | |
version (D_InlineAsm_X86) | |
{ | |
asm @safe pure nothrow @nogc | |
{ | |
mov EDI,dst ; | |
mov EAX,val ; | |
mov ECX,sz ; | |
mov EDX,EDI ; | |
rep ; | |
stosd ; | |
mov EAX,EDX ; | |
} | |
} | |
else | |
{ | |
scope uint* buf = cast(uint*) dst; | |
while(sz--) *buf++ = *cast(uint*) val; | |
return dst; | |
} | |
} | |
/// | |
unittest | |
{ | |
uint[10] buf; | |
uint val = 1234; | |
_d_memset!4(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
export void* _d_memset(size_t tsz: 8)(return scope void* dst, scope void* val, size_t sz) | |
{ | |
scope ulong* buf = cast(ulong*) dst; | |
while(sz--) *buf++ = *cast(ulong*) val; | |
return dst; | |
} | |
/// | |
unittest | |
{ | |
ulong[10] buf; | |
ulong val = 1234; | |
_d_memset!8(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
/// | |
unittest | |
{ | |
long[10] buf; | |
long val = 1234; | |
_d_memset!8(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
/// | |
unittest | |
{ | |
struct S { long l; } | |
S[10] buf; | |
S val = { l: 1234 }; | |
_d_memset!8(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
export void* _d_memset(size_t tsz: 16)(return scope void* dst, scope void* val, size_t sz) | |
{ | |
version(D_SIMD) | |
{ | |
import core.simd; | |
scope ubyte16* buf = cast(ubyte16*) dst; | |
while(sz--) *buf++ = *cast(ubyte16*) val; | |
return dst; | |
} | |
else | |
{ | |
align(1) static struct T128 { align(1): long _1; long _2; } | |
static assert(T128.sizeof == 16); | |
scope T128* buf = cast(T128*) dst; | |
while(sz--) *buf++ = *cast(T128*) val; | |
return dst; | |
} | |
} | |
/// | |
unittest | |
{ | |
struct S { long lo; long hi; } | |
S[10] buf; | |
S val = { lo: 1234, hi: 4321 }; | |
_d_memset!16(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
export void* _d_memset(size_t tsz: 32)(return scope void* dst, scope void* val, size_t sz) | |
{ | |
version(D_SIMD) | |
{ | |
import core.simd; | |
static if (is(ubyte32)) | |
{ | |
scope ubyte32* buf = cast(ubyte32*) dst; | |
while(sz--) *buf++ = *cast(ubyte32*) val; | |
return dst; | |
} | |
} | |
align(1) static struct T256 { align(1): long _1; long _2; long _3; long _4; } | |
static assert(T256.sizeof == 32); | |
scope T256* buf = cast(T256*) dst; | |
while(sz--) *buf++ = *cast(T256*) val; | |
return dst; | |
} | |
/// | |
unittest | |
{ | |
struct S { long l1; long l2; long l3; long l4; } | |
S[10] buf; | |
S val = { l1: 1, l2: 2, l3: 3, l4: 4 }; | |
_d_memset!32(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
export void* _d_memset(size_t tsz: 64)(return scope void* dst, scope void* val, size_t sz) | |
{ | |
align(1) static struct T512 { align(1): long _1; long _2; long _3; long _4; long _5; long _6; long _7; long _8; } | |
static assert(T512.sizeof == 64); | |
scope T512* buf = cast(T512*) dst; | |
while(sz--) *buf++ = *cast(T512*) val; | |
return dst; | |
} | |
/// | |
unittest | |
{ | |
struct S { long l1; long l2; long l3; long l4; long l5; long l6; long l7; long l8; } | |
S[10] buf; | |
S val = { l1: 1, l2: 2, l3: 3, l4: 4, l5: 5, l6: 6, l7: 7, l8: 8 }; | |
_d_memset!64(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} | |
export void* _d_memset(size_t tsz)(return scope void* dst, scope void* val, size_t sz) | |
{ | |
void* start = dst; | |
for (int i; i < sz; i++) | |
{ | |
import core.stdc.string : memcpy; | |
memcpy(dst, val, tsz); | |
dst = cast(void *)(cast(char *) dst + tsz); | |
} | |
return start; | |
} | |
/// | |
unittest | |
{ | |
struct S { long l1; long l2; long l3; long l4; long l5; long l6; long l7; long l8; long l9; } | |
S[10] buf; | |
S val = { l1: 1, l2: 2, l3: 3, l4: 4, l5: 5, l6: 6, l7: 7, l8: 8, l9: 9 }; | |
_d_memset!72(buf.ptr, &val, 10); | |
assert(buf[].equal(val.repeat(10))); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment