1 module bc.core.intrinsics; 2 3 version(LDC) 4 { 5 import ldc.intrinsics: llvm_expect; 6 import ldc.gccbuiltins_x86; 7 public import core.simd; 8 9 enum LDC_with_SSE42 = __traits(targetHasFeature, "sse4.2"); 10 11 // some definition aliases to commonly used names 12 alias __m128i = int4; 13 14 // some used methods aliases 15 alias _expect = llvm_expect; 16 alias _mm_loadu_si128 = loadUnaligned!__m128i; 17 alias _mm_cmpestri = __builtin_ia32_pcmpestri128; 18 19 // These specify the type of data that we're comparing. 20 enum _SIDD_UBYTE_OPS = 0x00; 21 enum _SIDD_UWORD_OPS = 0x01; 22 enum _SIDD_SBYTE_OPS = 0x02; 23 enum _SIDD_SWORD_OPS = 0x03; 24 25 // These specify the type of comparison operation. 26 enum _SIDD_CMP_EQUAL_ANY = 0x00; 27 enum _SIDD_CMP_RANGES = 0x04; 28 enum _SIDD_CMP_EQUAL_EACH = 0x08; 29 enum _SIDD_CMP_EQUAL_ORDERED = 0x0c; 30 31 // These are used in _mm_cmpXstri() to specify the return. 32 enum _SIDD_LEAST_SIGNIFICANT = 0x00; 33 enum _SIDD_MOST_SIGNIFICANT = 0x40; 34 35 // These macros are used in _mm_cmpXstri() to specify the return. 36 enum _SIDD_BIT_MASK = 0x00; 37 enum _SIDD_UNIT_MASK = 0x40; 38 } 39 else version(GNU) 40 { 41 import gcc.builtins: __builtin_expect, __builtin_clong; 42 43 /// 44 T _expect(T)(in T val, in T expected_val) if (__traits(isIntegral, T)) 45 { 46 static if (T.sizeof <= __builtin_clong.sizeof) 47 return cast(T) __builtin_expect(val, expected_val); 48 else 49 return val; 50 } 51 52 enum LDC_with_SSE42 = false; 53 } 54 else 55 { 56 /// 57 T _expect(T)(T val, T expected_val) if (__traits(isIntegral, T)) 58 { 59 return val; 60 } 61 62 enum LDC_with_SSE42 = false; 63 } 64 65 version (unittest) pragma(msg, "SSE: ", LDC_with_SSE42); 66 67 // Workarounds for betterC 68 version (D_BetterC) 69 { 70 pragma(mangle, "_D4core8lifetime16testEmplaceChunkFNaNbNiNfAvmmZv") 71 nothrow @nogc @safe pure void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment) {} 72 73 version (DigitalMars) 74 { 75 // see: https://issues.dlang.org/show_bug.cgi?id=19946 76 extern (C) nothrow @nogc: 77 78 short* _memset16(short *p, short value, size_t count) 79 { 80 short *pstart = p; 81 short *ptop; 82 83 for (ptop = &p[count]; p < ptop; p++) 84 *p = value; 85 return pstart; 86 } 87 88 int*_memset32(int *p, int value, size_t count) 89 { 90 version (D_InlineAsm_X86) 91 { 92 asm 93 { 94 mov EDI,p ; 95 mov EAX,value ; 96 mov ECX,count ; 97 mov EDX,EDI ; 98 rep ; 99 stosd ; 100 mov EAX,EDX ; 101 } 102 } 103 else 104 { 105 int *pstart = p; 106 int *ptop; 107 108 for (ptop = &p[count]; p < ptop; p++) 109 *p = value; 110 return pstart; 111 } 112 } 113 } 114 115 version (assert) 116 { 117 version (LDC) 118 { 119 // See: https://github.com/ldc-developers/ldc/issues/2425 120 // See: https://forum.dlang.org/post/heksucpdamkgwnztyitr@forum.dlang.org 121 extern(C) 122 nothrow @nogc 123 void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen, size_t elemsz) 124 { 125 import ldc.intrinsics : llvm_memcpy; 126 llvm_memcpy!size_t(dst, src, dstlen * elemsz, 0); 127 } 128 } 129 } 130 }