Created
August 4, 2022 12:23
-
-
Save ljmf00/14cd73e84521191f88b2bdc010ee1899 to your computer and use it in GitHub Desktop.
This file contains hidden or 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; | |
export void* _d_memset(size_t tsz)(void* dst, void[tsz] val, size_t sz) | |
{ | |
static if (tsz == 1) return setmem8 (dst, val, sz); | |
else static if (tsz == 2) return setmem16 (dst, val, sz); | |
else static if (tsz == 4) return setmem32 (dst, val, sz); | |
else static if (tsz == 8) return setmem64 (dst, val, sz); | |
else static if (tsz == 16) return setmem128(dst, val, sz); | |
else static if (tsz == 32) return setmem256(dst, val, sz); | |
else static if (tsz == 64) return setmem512(dst, val, sz); | |
else return setmemx (dst, val, sz); | |
} | |
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)); | |
} | |
} | |
private T* setmem8(T)(T* dst, T val, size_t sz) | |
if (T.sizeof == 1) | |
{ | |
version (LDC) | |
{ | |
llvm_memset(cast(void*)dst, *cast(ubyte*)&val, sz); | |
return dst; | |
} | |
else | |
{ | |
import core.stdc.string : memset; | |
return cast(T*) memset(dst, val, sz); | |
} | |
} | |
private T* setmem16(T)(T* dst, T 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 | |
{ | |
ushort* buf = *cast(ushort**)&dst; | |
while(sz--) *buf++ = *cast(ushort*)&val; | |
return dst; | |
} | |
} | |
private T* setmem32(T)(T* dst, T 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 | |
{ | |
uint* buf = *cast(uint**)&dst; | |
while(sz--) *buf++ = *cast(uint*)&val; | |
return dst; | |
} | |
} | |
private T* setmem64(T)(T* dst, T val, size_t sz) | |
{ | |
ulong* buf = *cast(ulong**)&dst; | |
while(sz--) *buf++ = *cast(ulong*)&val; | |
return dst; | |
} | |
private T* setmem128(T)(T* dst, T val, size_t sz) | |
{ | |
version(D_SIMD) | |
{ | |
import core.simd; | |
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); | |
T128* buf = *cast(T128**)&dst; | |
while(sz--) *buf++ = *cast(T128*)&val; | |
return dst; | |
} | |
} | |
private T* setmem256(T)(T* dst, T val, size_t sz) | |
{ | |
version(D_SIMD) | |
{ | |
import core.simd; | |
ubyte32* buf = *cast(ubyte32**)&dst; | |
while(sz--) *buf++ = *cast(ubyte32*)&val; | |
return dst; | |
} | |
else | |
{ | |
align(1) static struct T256 { align(1): long _1; long _2; } | |
static assert(T256.sizeof == 32); | |
T256* buf = *cast(T256**)&dst; | |
while(sz--) *buf++ = *cast(T256*)&val; | |
return dst; | |
} | |
} | |
private T* setmem512(T)(T* dst, T val, size_t sz) | |
{ | |
align(1) static struct T512 { align(1): long _1; long _2; long _3; long _4; } | |
static assert(T512.sizeof == 64); | |
T512* buf = *cast(T512**)&dst; | |
while(sz--) *buf++ = *cast(T512*)&val; | |
return dst; | |
} | |
private T* setmemx(T)(T* dst, T val, size_t sz) | |
{ | |
void *start = dst; | |
int i; | |
for (i = 0; i < count; i++) | |
{ | |
import core.stdc.string : memcpy; | |
memcpy(dst, &val, T.sizeof); | |
dst = cast(T*)(cast(ubyte*)dst + T.sizeof); | |
} | |
return start; | |
} | |
/// | |
unittest | |
{ | |
ubyte[10] buf; | |
setmem(buf.ptr, 123, 10); | |
assert(buf == [123, 123, 123, 123, 123, 123, 123, 123, 123, 123]); | |
} | |
/// | |
unittest | |
{ | |
ushort[10] buf; | |
setmem(buf.ptr, 1234, 10); | |
assert(buf == [1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234]); | |
} | |
/// | |
unittest | |
{ | |
uint[10] buf; | |
setmem(buf.ptr, 1234, 10); | |
assert(buf == [1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234]); | |
} | |
/// | |
unittest | |
{ | |
ulong[10] buf; | |
setmem(buf.ptr, 1234, 10); | |
assert(buf == [1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234]); | |
} | |
/// | |
unittest | |
{ | |
long[10] buf; | |
setmem(buf.ptr, 1234, 10); | |
assert(buf == [1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234]); | |
} | |
/// | |
unittest | |
{ | |
struct S { long l; } | |
S[10] buf; | |
setmem(buf.ptr, S(1234), 10); | |
assert(buf == | |
[S(1234),S(1234),S(1234),S(1234),S(1234),S(1234),S(1234),S(1234),S(1234),S(1234)]); | |
} | |
/// | |
unittest | |
{ | |
struct S { long lo; long hi; } | |
S[10] buf; | |
setmem(buf.ptr, S(1234, 4321), 10); | |
assert(buf == [S(1234, 4321),S(1234, 4321),S(1234, 4321),S(1234, | |
4321),S(1234, 4321),S(1234, 4321),S(1234, 4321),S(1234, | |
4321),S(1234, 4321),S(1234, 4321)]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment