2006-04-13 20:47:06 +00:00
|
|
|
// Function-wrapped Watcom pragmas
|
2012-03-12 04:47:04 +00:00
|
|
|
// by Jonathon Fowler (jf@jonof.id.au)
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// These functions represent some of the more longer-winded pragmas
|
|
|
|
// from the original pragmas.h wrapped into functions for easier
|
|
|
|
// use since many jumps and whatnot make it harder to write macro-
|
|
|
|
// inline versions. I'll eventually convert these to macro-inline
|
|
|
|
// equivalents. --Jonathon
|
|
|
|
|
|
|
|
#include "compat.h"
|
2014-10-25 03:29:21 +00:00
|
|
|
#include "pragmas.h"
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-06-25 11:29:50 +00:00
|
|
|
libdivide::libdivide_s64_t divtable64[DIVTABLESIZE];
|
|
|
|
libdivide::libdivide_s32_t divtable32[DIVTABLESIZE];
|
2012-05-01 12:37:32 +00:00
|
|
|
|
2015-09-27 21:18:12 +00:00
|
|
|
void initdivtables(void)
|
|
|
|
{
|
2018-10-25 23:33:52 +00:00
|
|
|
for (int i = 1; i < DIVTABLESIZE; ++i)
|
2015-09-27 21:18:12 +00:00
|
|
|
{
|
2019-06-25 11:29:50 +00:00
|
|
|
divtable64[i] = libdivide::libdivide_s64_gen(i);
|
|
|
|
divtable32[i] = libdivide::libdivide_s32_gen(i);
|
2015-09-27 21:18:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-25 03:29:21 +00:00
|
|
|
uint32_t divideu32_noinline(uint32_t n, uint32_t d) { return divideu32(n, d); }
|
|
|
|
int32_t tabledivide32_noinline(int32_t n, int32_t d) { return tabledivide32(n, d); }
|
2019-07-24 01:37:28 +00:00
|
|
|
int64_t tabledivide64_noinline(int64_t n, int64_t d) { return tabledivide64(n, d); }
|
2012-05-01 12:37:32 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-07-01 01:40:18 +00:00
|
|
|
//
|
|
|
|
// Generic C version
|
|
|
|
//
|
|
|
|
|
2017-01-23 11:21:22 +00:00
|
|
|
#ifndef pragmas_have_qinterpolatedown16
|
2009-01-09 09:29:17 +00:00
|
|
|
void qinterpolatedown16(intptr_t bufptr, int32_t num, int32_t val, int32_t add)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2018-10-25 23:29:54 +00:00
|
|
|
auto lptr = (int32_t *)bufptr;
|
2017-01-23 11:21:18 +00:00
|
|
|
for (size_t i = 0, i_end = num; i < i_end; ++i)
|
|
|
|
{
|
|
|
|
lptr[i] = val>>16;
|
|
|
|
val += add;
|
|
|
|
}
|
2006-07-01 01:40:18 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
void qinterpolatedown16short(intptr_t bufptr, int32_t num, int32_t val, int32_t add)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2018-10-25 23:29:54 +00:00
|
|
|
auto sptr = (int16_t *)bufptr;
|
2017-01-23 11:21:18 +00:00
|
|
|
for (size_t i = 0, i_end = num; i < i_end; ++i)
|
|
|
|
{
|
|
|
|
sptr[i] = val>>16;
|
|
|
|
val += add;
|
|
|
|
}
|
2006-07-01 01:40:18 +00:00
|
|
|
}
|
2017-01-23 11:21:22 +00:00
|
|
|
#endif
|
2006-07-01 01:40:18 +00:00
|
|
|
|
2017-01-23 11:21:22 +00:00
|
|
|
#ifndef pragmas_have_clearbuf
|
2009-01-09 09:29:17 +00:00
|
|
|
void clearbuf(void *d, int32_t c, int32_t a)
|
2006-07-01 01:40:18 +00:00
|
|
|
{
|
2018-10-25 23:29:54 +00:00
|
|
|
auto p = (int32_t *)d;
|
2012-02-18 22:14:45 +00:00
|
|
|
|
2017-01-23 11:21:18 +00:00
|
|
|
#if 0
|
|
|
|
if (a == 0)
|
|
|
|
{
|
|
|
|
clearbufbyte(d, c<<2, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
while (c--)
|
|
|
|
*p++ = a;
|
2006-07-01 01:40:18 +00:00
|
|
|
}
|
2017-01-23 11:21:22 +00:00
|
|
|
#endif
|
2006-07-01 01:40:18 +00:00
|
|
|
|
2017-01-23 11:21:22 +00:00
|
|
|
#ifndef pragmas_have_copybuf
|
2012-02-18 22:14:45 +00:00
|
|
|
void copybuf(const void *s, void *d, int32_t c)
|
2006-07-01 01:40:18 +00:00
|
|
|
{
|
2018-12-15 01:39:51 +00:00
|
|
|
auto p = (const int32_t *) s;
|
|
|
|
auto q = (int32_t *) d;
|
2012-02-18 22:14:45 +00:00
|
|
|
|
2017-01-23 11:21:18 +00:00
|
|
|
while (c--)
|
|
|
|
*q++ = *p++;
|
2006-07-01 01:40:18 +00:00
|
|
|
}
|
2017-01-23 11:21:22 +00:00
|
|
|
#endif
|
2006-07-01 01:40:18 +00:00
|
|
|
|
2017-01-23 11:21:22 +00:00
|
|
|
#ifndef pragmas_have_swaps
|
2009-01-09 09:29:17 +00:00
|
|
|
void swapbuf4(void *a, void *b, int32_t c)
|
2006-07-01 01:40:18 +00:00
|
|
|
{
|
2018-12-15 01:39:51 +00:00
|
|
|
auto p = (int32_t *) a;
|
|
|
|
auto q = (int32_t *) b;
|
2018-10-25 23:29:54 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
while ((c--) > 0)
|
|
|
|
{
|
2018-10-25 23:29:54 +00:00
|
|
|
int x = *q, y = *p;
|
2006-07-01 01:40:18 +00:00
|
|
|
*(q++) = y;
|
|
|
|
*(p++) = x;
|
|
|
|
}
|
|
|
|
}
|
2017-01-23 11:21:22 +00:00
|
|
|
#endif
|
2006-07-01 01:40:18 +00:00
|
|
|
|
2017-01-23 11:21:22 +00:00
|
|
|
#ifndef pragmas_have_clearbufbyte
|
2009-01-09 09:29:17 +00:00
|
|
|
void clearbufbyte(void *D, int32_t c, int32_t a)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
// Cringe City
|
2018-10-25 23:33:52 +00:00
|
|
|
constexpr int32_t m[4] = { 0xffl, 0xff00l, 0xff0000l, (int32_t)0xff000000l };
|
|
|
|
int z = 0;
|
2018-12-15 01:39:51 +00:00
|
|
|
auto p = (char *)D;
|
2015-07-11 23:07:47 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
while ((c--) > 0)
|
|
|
|
{
|
2015-07-11 23:07:47 +00:00
|
|
|
*(p++) = (uint8_t)((a & m[z])>>(z<<3));
|
2006-07-01 01:40:18 +00:00
|
|
|
z=(z+1)&3;
|
|
|
|
}
|
|
|
|
}
|
2017-01-23 11:21:22 +00:00
|
|
|
#endif
|
2006-07-01 01:40:18 +00:00
|
|
|
|
2017-01-23 11:21:22 +00:00
|
|
|
#ifndef pragmas_have_copybufbyte
|
2017-01-23 11:21:18 +00:00
|
|
|
void copybufbyte(const void *s, void *d, int32_t c)
|
2006-07-01 01:40:18 +00:00
|
|
|
{
|
2018-12-15 01:39:51 +00:00
|
|
|
auto src = (const char *)s;
|
|
|
|
auto dst = (char *)d;
|
2012-02-18 22:14:45 +00:00
|
|
|
|
2017-01-23 11:21:18 +00:00
|
|
|
while (c--)
|
|
|
|
*dst++ = *src++;
|
2006-07-01 01:40:18 +00:00
|
|
|
}
|
2017-01-23 11:21:22 +00:00
|
|
|
#endif
|
2006-07-01 01:40:18 +00:00
|
|
|
|
2014-03-05 21:12:58 +00:00
|
|
|
|
|
|
|
// copybufreverse() is a special case: use the assembly version for GCC on x86
|
|
|
|
// *and* x86_64, and the C version otherwise.
|
|
|
|
// XXX: we don't honor NOASM in the x86_64 case.
|
|
|
|
|
|
|
|
#if defined(__GNUC__) && defined(__x86_64__)
|
|
|
|
// NOTE: Almost CODEDUP from x86 GCC assembly version, except that
|
|
|
|
// - %%esi -> %%rsi
|
|
|
|
// - %%edi -> %%rdi
|
|
|
|
// - (dec,inc,sub,add)l suffix removed where necessary
|
|
|
|
void copybufreverse(const void *S, void *D, int32_t c)
|
|
|
|
{
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"shrl $1, %%ecx\n\t"
|
|
|
|
"jnc 0f\n\t" // jnc skipit1
|
|
|
|
"movb (%%rsi), %%al\n\t"
|
|
|
|
"dec %%rsi\n\t"
|
|
|
|
"movb %%al, (%%rdi)\n\t"
|
|
|
|
"inc %%rdi\n\t"
|
|
|
|
"0:\n\t" // skipit1:
|
|
|
|
"shrl $1, %%ecx\n\t"
|
|
|
|
"jnc 1f\n\t" // jnc skipit2
|
|
|
|
"movw -1(%%rsi), %%ax\n\t"
|
|
|
|
"sub $2, %%rsi\n\t"
|
|
|
|
"rorw $8, %%ax\n\t"
|
|
|
|
"movw %%ax, (%%rdi)\n\t"
|
|
|
|
"add $2, %%rdi\n\t"
|
|
|
|
"1:\n\t" // skipit2
|
|
|
|
"testl %%ecx, %%ecx\n\t"
|
|
|
|
"jz 3f\n\t" // jz endloop
|
|
|
|
"2:\n\t" // begloop
|
|
|
|
"movl -3(%%rsi), %%eax\n\t"
|
|
|
|
"sub $4, %%rsi\n\t"
|
|
|
|
"bswapl %%eax\n\t"
|
|
|
|
"movl %%eax, (%%rdi)\n\t"
|
|
|
|
"add $4, %%rdi\n\t"
|
|
|
|
"decl %%ecx\n\t"
|
|
|
|
"jnz 2b\n\t" // jnz begloop
|
|
|
|
"3:"
|
|
|
|
: "+S"(S), "+D"(D), "+c"(c) :
|
|
|
|
: "eax", "memory", "cc"
|
|
|
|
);
|
|
|
|
}
|
2017-01-23 11:21:22 +00:00
|
|
|
#elif !defined pragmas_have_copybufreverse
|
2017-01-23 11:21:18 +00:00
|
|
|
void copybufreverse(const void *s, void *d, int32_t c)
|
2006-07-01 01:40:18 +00:00
|
|
|
{
|
2018-12-15 01:39:51 +00:00
|
|
|
auto src = (const char *)s;
|
|
|
|
auto dst = (char *)d;
|
2012-02-18 22:14:45 +00:00
|
|
|
|
2017-01-23 11:21:18 +00:00
|
|
|
while (c--)
|
|
|
|
*dst++ = *src--;
|
2006-07-01 01:40:18 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|