root/coverage/lib/Headers/allegro5/platform/al386gcc.h

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. AL_INLINE
  2. AL_INLINE
  3. AL_INLINE
  4. AL_INLINE
  5. AL_INLINE

   1 /*         ______   ___    ___
   2  *        /\  _  \ /\_ \  /\_ \
   3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
   4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
   5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
   6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
   7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
   8  *                                           /\____/
   9  *                                           \_/__/
  10  *
  11  *      Inline functions (gcc style 386 asm).
  12  *
  13  *      By Shawn Hargreaves.
  14  *
  15  *      See readme.txt for copyright information.
  16  */
  17 
  18 
  19 #if (!defined ALLEGRO_GCC) || (!defined ALLEGRO_I386)
  20    #error bad include
  21 #endif
  22 
  23 #ifdef ALLEGRO_IMPORT_GFX_ASM
  24 
  25 /* _default_ds:
  26  *  Return a copy of the current %ds selector.
  27  */
  28 AL_INLINE(int, _default_ds, (void),
     /* [previous][next][first][last][top][bottom][index][help] */
  29 {
  30    short result;
  31 
  32    __asm__ (
  33       "  movw %%ds, %0 "
  34 
  35    : "=r" (result)
  36    );
  37 
  38    return result;
  39 })
  40 
  41 
  42 
  43 /* bmp_write_line:
  44  *  Bank switch function.
  45  */
  46 AL_INLINE(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne),
  47 {
  48    uintptr_t result;
  49 
  50    __asm__ volatile (
  51       "  call *%3 "
  52 
  53    : "=a" (result)                     /* result in eax */
  54 
  55    : "d" (bmp),                        /* bitmap in edx */
  56      "0" (lyne),                       /* line number in eax */
  57      "r" (bmp->write_bank)             /* the bank switch routine */
  58    );
  59 
  60    return result;
  61 })
  62 
  63 
  64 
  65 /* bmp_read_line:
  66  *  Bank switch function.
  67  */
  68 AL_INLINE(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne),
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70    uintptr_t result;
  71 
  72    __asm__ volatile (
  73       "  call *%3 "
  74 
  75    : "=a" (result)                     /* result in eax */
  76 
  77    : "d" (bmp),                        /* bitmap in edx */
  78      "0" (lyne),                       /* line number in eax */
  79      "r" (bmp->read_bank)              /* the bank switch routine */
  80    );
  81 
  82    return result;
  83 })
  84 
  85 
  86 
  87 /* bmp_unwrite_line:
  88  *  Terminate bank switch function.
  89  */
  90 AL_INLINE(void, bmp_unwrite_line, (BITMAP *bmp),
  91 {
  92    __asm__ volatile (
  93       "  call *%1 "
  94    :
  95    : "d" (bmp),                        /* bitmap in edx */
  96      "r" (bmp->vtable->unwrite_bank)   /* the bank switch routine */
  97    );
  98 })
  99 
 100 #endif /* ALLEGRO_IMPORT_GFX_ASM */
 101 
 102 
 103 #ifdef ALLEGRO_IMPORT_MATH_ASM
 104 
 105 /* Helper macro that makes the compiler reduce al_fixadd(), al_fixsub(), al_fixmul() and
 106    al_fixdiv() calls to a single constant if both operands are constant. Since
 107    this doesn't work unless we compile with optimization, it's better to skip
 108    the test then. */
 109 #if (defined __OPTIMIZE__) && ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)))
 110    #define __PRECALCULATE_CONSTANTS(calc)                                  \
 111       if(__builtin_constant_p(x) && __builtin_constant_p(y)) {             \
 112          if((calc) > (double)0x7FFFFFFF) {                                 \
 113             al_set_errno(ERANGE);                                          \
 114             return 0x7FFFFFFF;                                             \
 115          }                                                                 \
 116          else if(-(calc) > (double)0x7FFFFFFF) {                           \
 117             al_set_errno(ERANGE);                                          \
 118             return -0x7FFFFFFF;                                            \
 119          }                                                                 \
 120          else                                                              \
 121             return (al_fixed)(calc);                                       \
 122       }                                                                    \
 123       else
 124 #else
 125    #define __PRECALCULATE_CONSTANTS(calc)
 126 #endif
 127 
 128 
 129 
 130 /* al_fixadd:
 131  *  Fixed point (16.16) addition.
 132  */
 133 AL_INLINE(al_fixed, al_fixadd, (al_fixed x, al_fixed y),
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135    al_fixed result;
 136    int errnum = 0;
 137 
 138    __PRECALCULATE_CONSTANTS(x + (double)y)
 139    {
 140       __asm__ (
 141          "  addl %2, %0 ; "               /* do the addition */
 142          "  jno 0f ; "                    /* check for overflow */
 143 
 144          "  movl %4, %0 ; "               /* on overflow, set errno */
 145          "  movl %3, (%0) ; "
 146          "  movl $0x7FFFFFFF, %0 ; "      /* and return MAXINT */
 147          "  cmpl $0, %2 ; "
 148          "  jg 0f ; "
 149          "  negl %0 ; "
 150 
 151          " 0: "                           /* finished */
 152 
 153       : "=r" (result)                     /* result in a register */
 154 
 155       : "0" (x),                          /* x in the output register */
 156         "rm" (y),                         /* y can go in register or memory */
 157         "i" (ERANGE),
 158         "m" (errnum)
 159 
 160       : "%cc", "memory"                   /* clobbers flags and errno */
 161       );
 162 
 163       if (errnum)
 164          al_set_errno(errnum);
 165 
 166       return result;
 167    }
 168 })
 169 
 170 
 171 
 172 /* al_fixsub:
 173  *  Fixed point (16.16) subtraction.
 174  */
 175 AL_INLINE(al_fixed, al_fixsub, (al_fixed x, al_fixed y),
 176 {
 177    al_fixed result;
 178    int errnum = 0;
 179 
 180    __PRECALCULATE_CONSTANTS(x - (double)y)
 181    {
 182       __asm__ (
 183          "  subl %2, %0 ; "               /* do the subtraction */
 184          "  jno 0f ; "                    /* check for overflow */
 185 
 186          "  movl %4, %0 ; "               /* on overflow, set errno */
 187          "  movl %3, (%0) ; "
 188          "  movl $0x7FFFFFFF, %0 ; "      /* and return MAXINT */
 189          "  cmpl $0, %2 ; "
 190          "  jl 0f ; "
 191          "  negl %0 ; "
 192 
 193          " 0: "                           /* finished */
 194 
 195       : "=r" (result)                     /* result in a register */
 196 
 197       : "0" (x),                          /* x in the output register */
 198         "rm" (y),                         /* y can go in register or memory */
 199         "i" (ERANGE),
 200         "m" (errnum)
 201 
 202       : "%cc", "memory"                   /* clobbers flags and errno */
 203       );
 204 
 205       if (errnum)
 206          al_set_errno(errnum);
 207 
 208       return result;
 209    }
 210 })
 211 
 212 
 213 
 214 /* al_fixmul:
 215  *  Fixed point (16.16) multiplication.
 216  */
 217 AL_INLINE(al_fixed, al_fixmul, (al_fixed x, al_fixed y),
     /* [previous][next][first][last][top][bottom][index][help] */
 218 {
 219    al_fixed edx __attribute__ ((__unused__));
 220    al_fixed result;
 221    int errnum = 0;
 222 
 223    __PRECALCULATE_CONSTANTS(x / 65536.0 * y)
 224    {
 225       __asm__ (
 226          "  movl %2, %%eax ; "
 227          "  imull %3 ; "                  /* do the multiply */
 228          "  shrdl $16, %%edx, %%eax ; "
 229 
 230          "  sarl $15, %%edx ; "           /* check for overflow */
 231          "  jz 0f ; "
 232          "  cmpl $-1, %%edx ; "
 233          "  je 0f ; "
 234 
 235          "  movl %5, %%eax ; "            /* on overflow, set errno */
 236          "  movl %4, (%%eax) ; "
 237          "  movl $0x7FFFFFFF, %%eax ; "   /* and return MAXINT */
 238          "  cmpl $0, %2 ; "
 239          "  jge 1f ; "
 240          "  negl %%eax ; "
 241          " 1: "
 242          "  cmpl $0, %3 ; "
 243          "  jge 0f ; "
 244          "  negl %%eax ; "
 245 
 246          "  .balign 4, 0x90 ; "
 247 
 248          " 0: "                           /* finished */
 249 
 250       : "=&a" (result),                   /* the result has to go in eax */
 251         "=&d" (edx)                       /* reliably reserve edx */
 252 
 253       : "mr" (x),                         /* x and y can be regs or mem */
 254         "mr" (y),
 255         "i" (ERANGE),
 256         "m" (errnum)
 257 
 258       : "%cc", "memory"                   /* clobbers flags and errno */
 259       );
 260 
 261       if (errnum)
 262          al_set_errno(errnum);
 263 
 264       return result;
 265    }
 266 })
 267 
 268 
 269 
 270 /* al_fixdiv:
 271  *  Fixed point (16.16) division.
 272  */
 273 AL_INLINE(al_fixed, al_fixdiv, (al_fixed x, al_fixed y),
 274 {
 275    al_fixed edx __attribute__ ((__unused__));
 276    al_fixed reg __attribute__ ((__unused__));
 277    al_fixed result;
 278    int errnum = 0;
 279 
 280    __PRECALCULATE_CONSTANTS(x * 65536.0 / y)
 281    {
 282       __asm__ (
 283          "  testl %%eax, %%eax ; "        /* test sign of x */
 284          "  js 3f ; "
 285 
 286          "  testl %2, %2 ; "              /* test sign of y */
 287          "  jns 4f ; "
 288          "  negl %2 ; "
 289 
 290          " 0: "                           /* result will be negative */
 291          "  movl %%eax, %%edx ; "         /* check the range is ok */
 292          "  shrl $16, %%edx ; "
 293          "  shll $16, %%eax ; "
 294          "  cmpl %2, %%edx ; "
 295          "  jae 1f ; "
 296 
 297          "  divl %2 ; "                   /* do the divide */
 298          "  testl %%eax, %%eax ; "
 299          "  jns 2f ; "
 300 
 301          " 1: "
 302          "  movl %6, %%eax ; "            /* on overflow, set errno */
 303          "  movl %5, (%%eax) ; "
 304          "  movl $0x7FFFFFFF, %%eax ; "   /* and return MAXINT */
 305 
 306          " 2: "
 307          "  negl %%eax ; "                /* fix up the sign of the result */
 308          "  jmp 6f ; "
 309 
 310          "  .balign 4, 0x90 ; "
 311 
 312          " 3: "                           /* x is negative */
 313          "  negl %%eax ; "
 314          "  testl %2, %2 ; "              /* test sign of y */
 315          "  jns 0b ; "
 316          "  negl %2 ; "
 317 
 318          " 4: "                           /* result will be positive */
 319          "  movl %%eax, %%edx ; "         /* check the range is ok */
 320          "  shrl $16, %%edx ; "
 321          "  shll $16, %%eax ; "
 322          "  cmpl %2, %%edx ; "
 323          "  jae 5f ; "
 324 
 325          "  divl %2 ; "                   /* do the divide */
 326          "  testl %%eax, %%eax ; "
 327          "  jns 6f ; "
 328 
 329          " 5: "
 330          "  movl %6, %%eax ; "            /* on overflow, set errno */
 331          "  movl %5, (%%eax) ; "
 332          "  movl $0x7FFFFFFF, %%eax ; "   /* and return MAXINT */
 333 
 334          " 6: "                           /* finished */
 335 
 336       : "=a" (result),                    /* the result has to go in eax */
 337         "=&d" (edx),                      /* reliably reserve edx */
 338         "=r" (reg)                        /* input operand will be clobbered */
 339 
 340       : "0" (x),                          /* x in eax */
 341         "2" (y),                          /* y in register */
 342         "i" (ERANGE),
 343         "m" (errnum)
 344 
 345       : "%cc", "memory"                   /* clobbers flags and memory  */
 346       );
 347 
 348       if (errnum)
 349          al_set_errno(errnum);
 350 
 351       return result;
 352    }
 353 })
 354 
 355 
 356 
 357 /* al_fixfloor:
 358  * Fixed point version of floor().
 359  * Note that it returns an integer result (not a fixed one)
 360  */
 361 AL_INLINE(int, al_fixfloor, (al_fixed x),
     /* [previous][next][first][last][top][bottom][index][help] */
 362 {
 363    int result;
 364 
 365    __asm__ (
 366       " sarl $16, %0 "          /* convert to int */
 367 
 368     : "=r" (result)             /* result in a register */
 369 
 370     : "0" (x)                   /* x in the output register */
 371    );
 372 
 373    return result;
 374 })
 375 
 376 
 377 
 378 /* al_fixceil:
 379  * Fixed point version of ceil().
 380  * Note that it returns an integer result (not a fixed one)
 381  */
 382 AL_INLINE(int, al_fixceil, (al_fixed x),
 383 {
 384    int result;
 385    int errnum = 0;
 386 
 387    __asm__ (
 388       " addl $0xFFFF, %0 ;"     /* ceil () */
 389       " jns 0f ;"
 390       " jo 1f ;"
 391 
 392       "0:"
 393       " sarl $16, %0 ;"         /* convert to int */
 394       " jmp 2f ;"
 395 
 396       "1:"
 397       " movl %3, %0 ;"          /* on overflow, set errno */
 398       " movl %2, (%0) ;"
 399       " movl $0x7FFF, %0 ;"     /* and return large int */
 400 
 401       "2:"
 402     : "=r" (result)             /* result in a register */
 403 
 404     : "0" (x),                  /* x in the output register */
 405       "i" (ERANGE),
 406       "m" (errnum)
 407 
 408     : "%cc", "memory"           /* clobbers flags and errno */
 409    );
 410 
 411    if (errnum)
 412       al_set_errno(errnum);
 413 
 414    return result;
 415 })
 416 
 417 
 418 
 419 #undef __PRECALCULATE_CONSTANTS
 420 
 421 #endif /* ALLEGRO_IMPORT_MATH_ASM */
 422 

/* [previous][next][first][last][top][bottom][index][help] */