src/stdlib/SDL_stdlib.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 15 Mar 2013 01:01:20 -0400
changeset 7003 eeaf77005c30
parent 6885 700f1b25f77f
child 7180 3733e68edbc3
permissions -rw-r--r--
Improvements to stdlib.

All SDL_* functions are always available as real symbols, so you can always
link against them as a stable ABI. By default, however, all the things that
might have dithered down to macros in your application are now force-inlined,
to give you the same effect as before and theoretically better performance,
but still solve the classic macro problems.

Elsewhere, we provide real functions for these things that simply wrap the
inline functions, in case one needs to have a real function available.

Also: this exposed bugs: SDL_abs() does something different if you had the
macro vs the libc function, SDL_memcpy() returns a void* in the function
but not the macro, etc.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* This file contains portable stdlib functions for SDL */
    24 
    25 #include "SDL_stdinc.h"
    26 
    27 /* these are always #defined, make them real symbol in the library, too... */
    28 #undef SDL_ceil
    29 #undef SDL_abs
    30 #undef SDL_sinf
    31 #undef SDL_cosf
    32 #undef SDL_isdigit
    33 #undef SDL_isspace
    34 #undef SDL_toupper
    35 #undef SDL_tolower
    36 double SDL_ceil(double x) { return SDL_ceil_inline(x); }
    37 float SDL_cosf(float x) { return SDL_cosf_inline(x); }
    38 float SDL_sinf(float x) { return SDL_sinf_inline(x); }
    39 int SDL_abs(int x) { return SDL_abs_inline(x); }
    40 int SDL_isdigit(int x) { return SDL_isdigit_inline(x); }
    41 int SDL_isspace(int x) { return SDL_isspace_inline(x); }
    42 int SDL_toupper(int x) { return SDL_toupper_inline(x); }
    43 int SDL_tolower(int x) { return SDL_tolower_inline(x); }
    44 
    45 
    46 #ifndef HAVE_LIBC
    47 /* These are some C runtime intrinsics that need to be defined */
    48 
    49 #if defined(_MSC_VER)
    50 
    51 #ifndef __FLTUSED__
    52 #define __FLTUSED__
    53 __declspec(selectany) int _fltused = 1;
    54 #endif
    55 
    56 /* The optimizer on Visual Studio 2010/2012 generates memcpy() calls */
    57 #if _MSC_VER >= 1600 && defined(_WIN64) && !defined(_DEBUG)
    58 #include <intrin.h>
    59 
    60 #pragma function(memcpy)
    61 void * memcpy ( void * destination, const void * source, size_t num )
    62 {
    63     const Uint8 *src = (const Uint8 *)source;
    64     Uint8 *dst = (Uint8 *)destination;
    65     size_t i;
    66     
    67     /* All WIN64 architectures have SSE, right? */
    68     if (!((uintptr_t) src & 15) && !((uintptr_t) dst & 15)) {
    69         __m128 values[4];
    70         for (i = num / 64; i--;) {
    71             _mm_prefetch(src, _MM_HINT_NTA);
    72             values[0] = *(__m128 *) (src + 0);
    73             values[1] = *(__m128 *) (src + 16);
    74             values[2] = *(__m128 *) (src + 32);
    75             values[3] = *(__m128 *) (src + 48);
    76             _mm_stream_ps((float *) (dst + 0), values[0]);
    77             _mm_stream_ps((float *) (dst + 16), values[1]);
    78             _mm_stream_ps((float *) (dst + 32), values[2]);
    79             _mm_stream_ps((float *) (dst + 48), values[3]);
    80             src += 64;
    81             dst += 64;
    82         }
    83         num &= 63;
    84     }
    85 
    86     while (num--) {
    87         *dst++ = *src++;
    88     }
    89     return destination;
    90 }
    91 #endif /* _MSC_VER == 1600 && defined(_WIN64) && !defined(_DEBUG) */
    92 
    93 #ifdef _M_IX86
    94 
    95 void
    96 __declspec(naked)
    97 _chkstk()
    98 {
    99 }
   100 
   101 /* Float to long */
   102 void
   103 __declspec(naked)
   104 _ftol()
   105 {
   106     /* *INDENT-OFF* */
   107     __asm {
   108         push        ebp
   109         mov         ebp,esp
   110         sub         esp,20h
   111         and         esp,0FFFFFFF0h
   112         fld         st(0)
   113         fst         dword ptr [esp+18h]
   114         fistp       qword ptr [esp+10h]
   115         fild        qword ptr [esp+10h]
   116         mov         edx,dword ptr [esp+18h]
   117         mov         eax,dword ptr [esp+10h]
   118         test        eax,eax
   119         je          integer_QnaN_or_zero
   120 arg_is_not_integer_QnaN:
   121         fsubp       st(1),st
   122         test        edx,edx
   123         jns         positive
   124         fstp        dword ptr [esp]
   125         mov         ecx,dword ptr [esp]
   126         xor         ecx,80000000h
   127         add         ecx,7FFFFFFFh
   128         adc         eax,0
   129         mov         edx,dword ptr [esp+14h]
   130         adc         edx,0
   131         jmp         localexit
   132 positive:
   133         fstp        dword ptr [esp]
   134         mov         ecx,dword ptr [esp]
   135         add         ecx,7FFFFFFFh
   136         sbb         eax,0
   137         mov         edx,dword ptr [esp+14h]
   138         sbb         edx,0
   139         jmp         localexit
   140 integer_QnaN_or_zero:
   141         mov         edx,dword ptr [esp+14h]
   142         test        edx,7FFFFFFFh
   143         jne         arg_is_not_integer_QnaN
   144         fstp        dword ptr [esp+18h]
   145         fstp        dword ptr [esp+18h]
   146 localexit:
   147         leave
   148         ret
   149     }
   150     /* *INDENT-ON* */
   151 }
   152 
   153 void
   154 _ftol2_sse()
   155 {
   156     _ftol();
   157 }
   158 
   159 /* 64-bit math operators for 32-bit systems */
   160 void
   161 __declspec(naked)
   162 _allmul()
   163 {
   164     /* *INDENT-OFF* */
   165     __asm {
   166         push        ebp
   167         mov         ebp,esp
   168         push        edi
   169         push        esi
   170         push        ebx
   171         sub         esp,0Ch
   172         mov         eax,dword ptr [ebp+10h]
   173         mov         edi,dword ptr [ebp+8]
   174         mov         ebx,eax
   175         mov         esi,eax
   176         sar         esi,1Fh
   177         mov         eax,dword ptr [ebp+8]
   178         mul         ebx
   179         imul        edi,esi
   180         mov         ecx,edx
   181         mov         dword ptr [ebp-18h],eax
   182         mov         edx,dword ptr [ebp+0Ch]
   183         add         ecx,edi
   184         imul        ebx,edx
   185         mov         eax,dword ptr [ebp-18h]
   186         lea         ebx,[ebx+ecx]
   187         mov         dword ptr [ebp-14h],ebx
   188         mov         edx,dword ptr [ebp-14h]
   189         add         esp,0Ch
   190         pop         ebx
   191         pop         esi
   192         pop         edi
   193         pop         ebp
   194         ret
   195     }
   196     /* *INDENT-ON* */
   197 }
   198 
   199 void
   200 __declspec(naked)
   201 _alldiv()
   202 {
   203     /* *INDENT-OFF* */
   204     __asm {
   205         push        edi
   206         push        esi
   207         push        ebx
   208         xor         edi,edi
   209         mov         eax,dword ptr [esp+14h]
   210         or          eax,eax
   211         jge         L1
   212         inc         edi
   213         mov         edx,dword ptr [esp+10h]
   214         neg         eax
   215         neg         edx
   216         sbb         eax,0
   217         mov         dword ptr [esp+14h],eax
   218         mov         dword ptr [esp+10h],edx
   219 L1:
   220         mov         eax,dword ptr [esp+1Ch]
   221         or          eax,eax
   222         jge         L2
   223         inc         edi
   224         mov         edx,dword ptr [esp+18h]
   225         neg         eax
   226         neg         edx
   227         sbb         eax,0
   228         mov         dword ptr [esp+1Ch],eax
   229         mov         dword ptr [esp+18h],edx
   230 L2:
   231         or          eax,eax
   232         jne         L3
   233         mov         ecx,dword ptr [esp+18h]
   234         mov         eax,dword ptr [esp+14h]
   235         xor         edx,edx
   236         div         ecx
   237         mov         ebx,eax
   238         mov         eax,dword ptr [esp+10h]
   239         div         ecx
   240         mov         edx,ebx
   241         jmp         L4
   242 L3:
   243         mov         ebx,eax
   244         mov         ecx,dword ptr [esp+18h]
   245         mov         edx,dword ptr [esp+14h]
   246         mov         eax,dword ptr [esp+10h]
   247 L5:
   248         shr         ebx,1
   249         rcr         ecx,1
   250         shr         edx,1
   251         rcr         eax,1
   252         or          ebx,ebx
   253         jne         L5
   254         div         ecx
   255         mov         esi,eax
   256         mul         dword ptr [esp+1Ch]
   257         mov         ecx,eax
   258         mov         eax,dword ptr [esp+18h]
   259         mul         esi
   260         add         edx,ecx
   261         jb          L6
   262         cmp         edx,dword ptr [esp+14h]
   263         ja          L6
   264         jb          L7
   265         cmp         eax,dword ptr [esp+10h]
   266         jbe         L7
   267 L6:
   268         dec         esi
   269 L7:
   270         xor         edx,edx
   271         mov         eax,esi
   272 L4:
   273         dec         edi
   274         jne         L8
   275         neg         edx
   276         neg         eax
   277         sbb         edx,0
   278 L8:
   279         pop         ebx
   280         pop         esi
   281         pop         edi
   282         ret         10h
   283     }
   284     /* *INDENT-ON* */
   285 }
   286 
   287 void
   288 __declspec(naked)
   289 _aulldiv()
   290 {
   291     /* *INDENT-OFF* */
   292     __asm {
   293         push        ebx
   294         push        esi
   295         mov         eax,dword ptr [esp+18h]
   296         or          eax,eax
   297         jne         L1
   298         mov         ecx,dword ptr [esp+14h]
   299         mov         eax,dword ptr [esp+10h]
   300         xor         edx,edx
   301         div         ecx
   302         mov         ebx,eax
   303         mov         eax,dword ptr [esp+0Ch]
   304         div         ecx
   305         mov         edx,ebx
   306         jmp         L2
   307 L1:
   308         mov         ecx,eax
   309         mov         ebx,dword ptr [esp+14h]
   310         mov         edx,dword ptr [esp+10h]
   311         mov         eax,dword ptr [esp+0Ch]
   312 L3:
   313         shr         ecx,1
   314         rcr         ebx,1
   315         shr         edx,1
   316         rcr         eax,1
   317         or          ecx,ecx
   318         jne         L3
   319         div         ebx
   320         mov         esi,eax
   321         mul         dword ptr [esp+18h]
   322         mov         ecx,eax
   323         mov         eax,dword ptr [esp+14h]
   324         mul         esi
   325         add         edx,ecx
   326         jb          L4
   327         cmp         edx,dword ptr [esp+10h]
   328         ja          L4
   329         jb          L5
   330         cmp         eax,dword ptr [esp+0Ch]
   331         jbe         L5
   332 L4:
   333         dec         esi
   334 L5:
   335         xor         edx,edx
   336         mov         eax,esi
   337 L2:
   338         pop         esi
   339         pop         ebx
   340         ret         10h
   341     }
   342     /* *INDENT-ON* */
   343 }
   344 
   345 void
   346 __declspec(naked)
   347 _allrem()
   348 {
   349     /* *INDENT-OFF* */
   350     __asm {
   351         push        ebx
   352         push        edi
   353         xor         edi,edi
   354         mov         eax,dword ptr [esp+10h]
   355         or          eax,eax
   356         jge         L1
   357         inc         edi
   358         mov         edx,dword ptr [esp+0Ch]
   359         neg         eax
   360         neg         edx
   361         sbb         eax,0
   362         mov         dword ptr [esp+10h],eax
   363         mov         dword ptr [esp+0Ch],edx
   364 L1:
   365         mov         eax,dword ptr [esp+18h]
   366         or          eax,eax
   367         jge         L2
   368         mov         edx,dword ptr [esp+14h]
   369         neg         eax
   370         neg         edx
   371         sbb         eax,0
   372         mov         dword ptr [esp+18h],eax
   373         mov         dword ptr [esp+14h],edx
   374 L2:
   375         or          eax,eax
   376         jne         L3
   377         mov         ecx,dword ptr [esp+14h]
   378         mov         eax,dword ptr [esp+10h]
   379         xor         edx,edx
   380         div         ecx
   381         mov         eax,dword ptr [esp+0Ch]
   382         div         ecx
   383         mov         eax,edx
   384         xor         edx,edx
   385         dec         edi
   386         jns         L4
   387         jmp         L8
   388 L3:
   389         mov         ebx,eax
   390         mov         ecx,dword ptr [esp+14h]
   391         mov         edx,dword ptr [esp+10h]
   392         mov         eax,dword ptr [esp+0Ch]
   393 L5:
   394         shr         ebx,1
   395         rcr         ecx,1
   396         shr         edx,1
   397         rcr         eax,1
   398         or          ebx,ebx
   399         jne         L5
   400         div         ecx
   401         mov         ecx,eax
   402         mul         dword ptr [esp+18h]
   403         xchg        eax,ecx
   404         mul         dword ptr [esp+14h]
   405         add         edx,ecx
   406         jb          L6
   407         cmp         edx,dword ptr [esp+10h]
   408         ja          L6
   409         jb          L7
   410         cmp         eax,dword ptr [esp+0Ch]
   411         jbe         L7
   412 L6:
   413         sub         eax,dword ptr [esp+14h]
   414         sbb         edx,dword ptr [esp+18h]
   415 L7:
   416         sub         eax,dword ptr [esp+0Ch]
   417         sbb         edx,dword ptr [esp+10h]
   418         dec         edi
   419         jns         L8
   420 L4:
   421         neg         edx
   422         neg         eax
   423         sbb         edx,0
   424 L8:
   425         pop         edi
   426         pop         ebx
   427         ret         10h
   428     }
   429     /* *INDENT-ON* */
   430 }
   431 
   432 void
   433 __declspec(naked)
   434 _aullrem()
   435 {
   436     /* *INDENT-OFF* */
   437     __asm {
   438         push        ebx
   439         mov         eax,dword ptr [esp+14h]
   440         or          eax,eax
   441         jne         L1
   442         mov         ecx,dword ptr [esp+10h]
   443         mov         eax,dword ptr [esp+0Ch]
   444         xor         edx,edx
   445         div         ecx
   446         mov         eax,dword ptr [esp+8]
   447         div         ecx
   448         mov         eax,edx
   449         xor         edx,edx
   450         jmp         L2
   451 L1:
   452         mov         ecx,eax
   453         mov         ebx,dword ptr [esp+10h]
   454         mov         edx,dword ptr [esp+0Ch]
   455         mov         eax,dword ptr [esp+8]
   456 L3:
   457         shr         ecx,1
   458         rcr         ebx,1
   459         shr         edx,1
   460         rcr         eax,1
   461         or          ecx,ecx
   462         jne         L3
   463         div         ebx
   464         mov         ecx,eax
   465         mul         dword ptr [esp+14h]
   466         xchg        eax,ecx
   467         mul         dword ptr [esp+10h]
   468         add         edx,ecx
   469         jb          L4
   470         cmp         edx,dword ptr [esp+0Ch]
   471         ja          L4
   472         jb          L5
   473         cmp         eax,dword ptr [esp+8]
   474         jbe         L5
   475 L4:
   476         sub         eax,dword ptr [esp+10h]
   477         sbb         edx,dword ptr [esp+14h]
   478 L5:
   479         sub         eax,dword ptr [esp+8]
   480         sbb         edx,dword ptr [esp+0Ch]
   481         neg         edx
   482         neg         eax
   483         sbb         edx,0
   484 L2:
   485         pop         ebx
   486         ret         10h
   487     }
   488     /* *INDENT-ON* */
   489 }
   490 
   491 void
   492 __declspec(naked)
   493 _alldvrm()
   494 {
   495     /* *INDENT-OFF* */
   496     __asm {
   497         push        edi
   498         push        esi
   499         push        ebp
   500         xor         edi,edi
   501         xor         ebp,ebp
   502         mov         eax,dword ptr [esp+14h]
   503         or          eax,eax
   504         jge         L1
   505         inc         edi
   506         inc         ebp
   507         mov         edx,dword ptr [esp+10h]
   508         neg         eax
   509         neg         edx
   510         sbb         eax,0
   511         mov         dword ptr [esp+14h],eax
   512         mov         dword ptr [esp+10h],edx
   513 L1:
   514         mov         eax,dword ptr [esp+1Ch]
   515         or          eax,eax
   516         jge         L2
   517         inc         edi
   518         mov         edx,dword ptr [esp+18h]
   519         neg         eax
   520         neg         edx
   521         sbb         eax,0
   522         mov         dword ptr [esp+1Ch],eax
   523         mov         dword ptr [esp+18h],edx
   524 L2:
   525         or          eax,eax
   526         jne         L3
   527         mov         ecx,dword ptr [esp+18h]
   528         mov         eax,dword ptr [esp+14h]
   529         xor         edx,edx
   530         div         ecx
   531         mov         ebx,eax
   532         mov         eax,dword ptr [esp+10h]
   533         div         ecx
   534         mov         esi,eax
   535         mov         eax,ebx
   536         mul         dword ptr [esp+18h]
   537         mov         ecx,eax
   538         mov         eax,esi
   539         mul         dword ptr [esp+18h]
   540         add         edx,ecx
   541         jmp         L4
   542 L3:
   543         mov         ebx,eax
   544         mov         ecx,dword ptr [esp+18h]
   545         mov         edx,dword ptr [esp+14h]
   546         mov         eax,dword ptr [esp+10h]
   547 L5:
   548         shr         ebx,1
   549         rcr         ecx,1
   550         shr         edx,1
   551         rcr         eax,1
   552         or          ebx,ebx
   553         jne         L5
   554         div         ecx
   555         mov         esi,eax
   556         mul         dword ptr [esp+1Ch]
   557         mov         ecx,eax
   558         mov         eax,dword ptr [esp+18h]
   559         mul         esi
   560         add         edx,ecx
   561         jb          L6
   562         cmp         edx,dword ptr [esp+14h]
   563         ja          L6
   564         jb          L7
   565         cmp         eax,dword ptr [esp+10h]
   566         jbe         L7
   567 L6:
   568         dec         esi
   569         sub         eax,dword ptr [esp+18h]
   570         sbb         edx,dword ptr [esp+1Ch]
   571 L7:
   572         xor         ebx,ebx
   573 L4:
   574         sub         eax,dword ptr [esp+10h]
   575         sbb         edx,dword ptr [esp+14h]
   576         dec         ebp
   577         jns         L9
   578         neg         edx
   579         neg         eax
   580         sbb         edx,0
   581 L9:
   582         mov         ecx,edx
   583         mov         edx,ebx
   584         mov         ebx,ecx
   585         mov         ecx,eax
   586         mov         eax,esi
   587         dec         edi
   588         jne         L8
   589         neg         edx
   590         neg         eax
   591         sbb         edx,0
   592 L8:
   593         pop         ebp
   594         pop         esi
   595         pop         edi
   596         ret         10h
   597     }
   598     /* *INDENT-ON* */
   599 }
   600 
   601 void
   602 __declspec(naked)
   603 _aulldvrm()
   604 {
   605     /* *INDENT-OFF* */
   606     __asm {
   607         push        esi
   608         mov         eax,dword ptr [esp+14h]
   609         or          eax,eax
   610         jne         L1
   611         mov         ecx,dword ptr [esp+10h]
   612         mov         eax,dword ptr [esp+0Ch]
   613         xor         edx,edx
   614         div         ecx
   615         mov         ebx,eax
   616         mov         eax,dword ptr [esp+8]
   617         div         ecx
   618         mov         esi,eax
   619         mov         eax,ebx
   620         mul         dword ptr [esp+10h]
   621         mov         ecx,eax
   622         mov         eax,esi
   623         mul         dword ptr [esp+10h]
   624         add         edx,ecx
   625         jmp         L2
   626 L1:
   627         mov         ecx,eax
   628         mov         ebx,dword ptr [esp+10h]
   629         mov         edx,dword ptr [esp+0Ch]
   630         mov         eax,dword ptr [esp+8]
   631 L3:
   632         shr         ecx,1
   633         rcr         ebx,1
   634         shr         edx,1
   635         rcr         eax,1
   636         or          ecx,ecx
   637         jne         L3
   638         div         ebx
   639         mov         esi,eax
   640         mul         dword ptr [esp+14h]
   641         mov         ecx,eax
   642         mov         eax,dword ptr [esp+10h]
   643         mul         esi
   644         add         edx,ecx
   645         jb          L4
   646         cmp         edx,dword ptr [esp+0Ch]
   647         ja          L4
   648         jb          L5
   649         cmp         eax,dword ptr [esp+8]
   650         jbe         L5
   651 L4:
   652         dec         esi
   653         sub         eax,dword ptr [esp+10h]
   654         sbb         edx,dword ptr [esp+14h]
   655 L5:
   656         xor         ebx,ebx
   657 L2:
   658         sub         eax,dword ptr [esp+8]
   659         sbb         edx,dword ptr [esp+0Ch]
   660         neg         edx
   661         neg         eax
   662         sbb         edx,0
   663         mov         ecx,edx
   664         mov         edx,ebx
   665         mov         ebx,ecx
   666         mov         ecx,eax
   667         mov         eax,esi
   668         pop         esi
   669         ret         10h
   670     }
   671     /* *INDENT-ON* */
   672 }
   673 
   674 void
   675 __declspec(naked)
   676 _allshl()
   677 {
   678     /* *INDENT-OFF* */
   679     __asm {
   680         cmp         cl,40h
   681         jae         RETZERO
   682         cmp         cl,20h
   683         jae         MORE32
   684         shld        edx,eax,cl
   685         shl         eax,cl
   686         ret
   687 MORE32:
   688         mov         edx,eax
   689         xor         eax,eax
   690         and         cl,1Fh
   691         shl         edx,cl
   692         ret
   693 RETZERO:
   694         xor         eax,eax
   695         xor         edx,edx
   696         ret
   697     }
   698     /* *INDENT-ON* */
   699 }
   700 
   701 void
   702 __declspec(naked)
   703 _allshr()
   704 {
   705     /* *INDENT-OFF* */
   706     __asm {
   707         cmp         cl,40h
   708         jae         RETZERO
   709         cmp         cl,20h
   710         jae         MORE32
   711         shrd        eax,edx,cl
   712         sar         edx,cl
   713         ret
   714 MORE32:
   715         mov         eax,edx
   716         xor         edx,edx
   717         and         cl,1Fh
   718         sar         eax,cl
   719         ret
   720 RETZERO:
   721         xor         eax,eax
   722         xor         edx,edx
   723         ret
   724     }
   725     /* *INDENT-ON* */
   726 }
   727 
   728 void
   729 __declspec(naked)
   730 _aullshr()
   731 {
   732     /* *INDENT-OFF* */
   733     __asm {
   734         cmp         cl,40h
   735         jae         RETZERO
   736         cmp         cl,20h
   737         jae         MORE32
   738         shrd        eax,edx,cl
   739         shr         edx,cl
   740         ret
   741 MORE32:
   742         mov         eax,edx
   743         xor         edx,edx
   744         and         cl,1Fh
   745         shr         eax,cl
   746         ret
   747 RETZERO:
   748         xor         eax,eax
   749         xor         edx,edx
   750         ret
   751     }
   752     /* *INDENT-ON* */
   753 }
   754 
   755 #endif /* _M_IX86 */
   756 
   757 #endif /* MSC_VER */
   758 
   759 #endif /* !HAVE_LIBC */
   760 
   761 /* vi: set ts=4 sw=4 expandtab: */