1 /**
2  * Contains a memset implementation used by compiler-generated code.
3  *
4  * Copyright: Copyright Digital Mars 2004 - 2010.
5  * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6  * Authors:   Walter Bright
7  */
8 
9 /*          Copyright Digital Mars 2004 - 2010.
10  * Distributed under the Boost Software License, Version 1.0.
11  *    (See accompanying file LICENSE or copy at
12  *          http://www.boost.org/LICENSE_1_0.txt)
13  */
14 module miniruntime.memset;
15 
16 /*
17    In -betterC mode, the compiler should use libc's memset instead of _memset32 in Dlang's
18    runtime to init memory. However, dmd incorrectly generate _memset32, so we need to polyfill it.
19 
20    Bug example: https://run.dlang.io/is/7TUsX5
21    Bug report: https://issues.dlang.org/show_bug.cgi?id=17778
22  */
23 version(DigitalMars) {
24 
25     @nogc:
26         nothrow:
27         @trusted:
28 
29         extern (C)
30         {
31             // Functions from the C library.
32             void *memcpy(void *, void *, size_t);
33         }
34 
35     extern (C):
36 
37         short *_memset16(short *p, short value, size_t count)
38         {
39             short *pstart = p;
40             short *ptop;
41 
42             for (ptop = &p[count]; p < ptop; p++)
43                 *p = value;
44             return pstart;
45         }
46 
47     int *_memset32(int *p, int value, size_t count)
48     {
49         version (D_InlineAsm_X86)
50         {
51             asm @nogc nothrow
52             {
53                 mov     EDI,p           ;
54                 mov     EAX,value       ;
55                 mov     ECX,count       ;
56                 mov     EDX,EDI         ;
57                 rep                     ;
58                 stosd                   ;
59                 mov     EAX,EDX         ;
60             }
61         }
62         else
63         {
64             int *pstart = p;
65             int *ptop;
66 
67             for (ptop = &p[count]; p < ptop; p++)
68                 *p = value;
69             return pstart;
70         }
71     }
72 
73     long *_memset64(long *p, long value, size_t count)
74     {
75         long *pstart = p;
76         long *ptop;
77 
78         for (ptop = &p[count]; p < ptop; p++)
79             *p = value;
80         return pstart;
81     }
82 
83     cdouble *_memset128(cdouble *p, cdouble value, size_t count)
84     {
85         cdouble *pstart = p;
86         cdouble *ptop;
87 
88         for (ptop = &p[count]; p < ptop; p++)
89             *p = value;
90         return pstart;
91     }
92 
93     void[] *_memset128ii(void[] *p, void[] value, size_t count)
94     {
95         void[] *pstart = p;
96         void[] *ptop;
97 
98         for (ptop = &p[count]; p < ptop; p++)
99             *p = value;
100         return pstart;
101     }
102 
103     real *_memset80(real *p, real value, size_t count)
104     {
105         real *pstart = p;
106         real *ptop;
107 
108         for (ptop = &p[count]; p < ptop; p++)
109             *p = value;
110         return pstart;
111     }
112 
113     creal *_memset160(creal *p, creal value, size_t count)
114     {
115         creal *pstart = p;
116         creal *ptop;
117 
118         for (ptop = &p[count]; p < ptop; p++)
119             *p = value;
120         return pstart;
121     }
122 
123     void *_memsetn(void *p, void *value, int count, size_t sizelem)
124     {   void *pstart = p;
125         int i;
126 
127         for (i = 0; i < count; i++)
128         {
129             memcpy(p, value, sizelem);
130             p = cast(void *)(cast(char *)p + sizelem);
131         }
132         return pstart;
133     }
134 
135     float *_memsetFloat(float *p, float value, size_t count)
136     {
137         float *pstart = p;
138         float *ptop;
139 
140         for (ptop = &p[count]; p < ptop; p++)
141             *p = value;
142         return pstart;
143     }
144 
145     double *_memsetDouble(double *p, double value, size_t count)
146     {
147         double *pstart = p;
148         double *ptop;
149 
150         for (ptop = &p[count]; p < ptop; p++)
151             *p = value;
152         return pstart;
153     }
154 
155     version (D_SIMD)
156     {
157         import core.simd;
158 
159         void16* _memsetSIMD(void16 *p, void16 value, size_t count)
160         {
161             foreach (i; 0..count)
162                 p[i] = value;
163             return p;
164         }
165     }
166 }