Subversion Repositories eduke32

Rev

Rev 5009 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
// This file has been modified from Ken Silverman's original release
2456 hendricks2 2
// by Jonathon Fowler (jf@jonof.id.au)
5 Plagman 3
 
4
 
4747 terminx 5
#ifndef pragmas_h_
6
#define pragmas_h_
5 Plagman 7
 
4766 hendricks2 8
#ifdef __cplusplus
201 terminx 9
extern "C" {
10
#endif
11
 
1492 terminx 12
#include <limits.h>
13
 
4715 terminx 14
#define EDUKE32_GENERATE_PRAGMAS                                                                                       \
15
    EDUKE32_SCALER_PRAGMA(1) EDUKE32_SCALER_PRAGMA(2) EDUKE32_SCALER_PRAGMA(3) EDUKE32_SCALER_PRAGMA(4)                \
16
    EDUKE32_SCALER_PRAGMA(5) EDUKE32_SCALER_PRAGMA(6) EDUKE32_SCALER_PRAGMA(7) EDUKE32_SCALER_PRAGMA(8)                \
17
    EDUKE32_SCALER_PRAGMA(9) EDUKE32_SCALER_PRAGMA(10) EDUKE32_SCALER_PRAGMA(11) EDUKE32_SCALER_PRAGMA(12)             \
18
    EDUKE32_SCALER_PRAGMA(13) EDUKE32_SCALER_PRAGMA(14) EDUKE32_SCALER_PRAGMA(15) EDUKE32_SCALER_PRAGMA(16)            \
19
    EDUKE32_SCALER_PRAGMA(17) EDUKE32_SCALER_PRAGMA(18) EDUKE32_SCALER_PRAGMA(19) EDUKE32_SCALER_PRAGMA(20)            \
20
    EDUKE32_SCALER_PRAGMA(21) EDUKE32_SCALER_PRAGMA(22) EDUKE32_SCALER_PRAGMA(23) EDUKE32_SCALER_PRAGMA(24)            \
21
    EDUKE32_SCALER_PRAGMA(25) EDUKE32_SCALER_PRAGMA(26) EDUKE32_SCALER_PRAGMA(27) EDUKE32_SCALER_PRAGMA(28)            \
22
    EDUKE32_SCALER_PRAGMA(29) EDUKE32_SCALER_PRAGMA(30) EDUKE32_SCALER_PRAGMA(31)
4601 terminx 23
 
1205 terminx 24
extern int32_t dmval;
4661 terminx 25
#if !defined(NOASM) && defined __cplusplus
26
extern "C" {
27
#endif
28
extern int32_t reciptable[2048], fpuasm;
29
#if !defined(NOASM) && defined __cplusplus
4766 hendricks2 30
}
4661 terminx 31
#endif
5 Plagman 32
 
1492 terminx 33
// break the C version of divscale out from the others
34
// because asm version overflows in drawmapview()
35
 
4715 terminx 36
#define qw(x) ((int64_t)(x))  // quadword cast
37
#define dw(x) ((int32_t)(x))  // doubleword cast
38
#define wo(x) ((int16_t)(x))  // word cast
39
#define by(x) ((uint8_t)(x))  // byte cast
1492 terminx 40
 
4658 terminx 41
#define LIBDIVIDE_ALWAYS
42
#define DIVTABLESIZE 16384
4577 helixhorne 43
 
4658 terminx 44
extern libdivide_s64pad_t divtable64[DIVTABLESIZE];
45
extern libdivide_s32pad_t divtable32[DIVTABLESIZE];
46
 
47
#if defined(__arm__) || defined(LIBDIVIDE_ALWAYS)
48
static inline uint32_t divideu32(uint32_t n, uint32_t d)
2621 helixhorne 49
{
4658 terminx 50
    static libdivide_u32_t udiv;
51
    static uint32_t lastd;
52
 
53
    if (d == lastd)
54
        goto skip;
55
 
56
    lastd = d;
57
    udiv = libdivide_u32_gen(d);
58
skip:
59
    return libdivide_u32_do(n, &udiv);
2621 helixhorne 60
}
61
 
4658 terminx 62
static inline int32_t tabledivide64(int64_t n, int32_t d)
63
{
64
    static libdivide_s64_t sdiv;
65
    static int32_t lastd;
4715 terminx 66
    libdivide_s64_t *dptr = ((unsigned)d < DIVTABLESIZE) ? (libdivide_s64_t *)&divtable64[d] : &sdiv;
2621 helixhorne 67
 
4658 terminx 68
    if (d == lastd || dptr != &sdiv)
69
        goto skip;
70
 
71
    lastd = d;
72
    sdiv = libdivide_s64_gen(d);
73
skip:
74
    return libdivide_s64_do(n, dptr);
75
}
76
 
77
static inline int32_t tabledivide32(int32_t n, int32_t d)
78
{
79
    static libdivide_s32_t sdiv;
80
    static int32_t lastd;
4715 terminx 81
    libdivide_s32_t *dptr = ((unsigned)d < DIVTABLESIZE) ? (libdivide_s32_t *)&divtable32[d] : &sdiv;
4658 terminx 82
 
83
    if (d == lastd || dptr != &sdiv)
84
        goto skip;
85
 
86
    lastd = d;
87
    sdiv = libdivide_s32_gen(d);
88
skip:
89
    return libdivide_s32_do(n, dptr);
90
}
2621 helixhorne 91
#else
4658 terminx 92
static inline uint32_t divideu32(uint32_t n, uint32_t d) { return n / d; }
2621 helixhorne 93
 
4715 terminx 94
static inline int32_t tabledivide64(int64_t n, int32_t d)
95
{
96
    return ((unsigned)d < DIVTABLESIZE) ? libdivide_s64_do(n, (libdivide_s64_t *)&divtable64[d]) : n / d;
97
}
1492 terminx 98
 
4715 terminx 99
static inline int32_t tabledivide32(int32_t n, int32_t d)
100
{
101
    return ((unsigned)d < DIVTABLESIZE) ? libdivide_s32_do(n, (libdivide_s32_t *)&divtable32[d]) : n / d;
102
}
2621 helixhorne 103
#endif
104
 
4658 terminx 105
extern uint32_t divideu32_noinline(uint32_t n, uint32_t d);
106
extern int32_t tabledivide32_noinline(int32_t n, int32_t d);
107
extern int32_t tabledivide64_noinline(int64_t n, int32_t d);
108
 
109
#ifdef GEKKO
110
#include <math.h>
4715 terminx 111
static inline int32_t divscale(int32_t eax, int32_t ebx, int32_t ecx) { return tabledivide64(ldexp(eax, ecx), ebx); }
4658 terminx 112
#else
113
static inline int32_t divscale(int32_t eax, int32_t ebx, int32_t ecx)
114
{
115
    const int64_t numer = qw(eax) << by(ecx);
116
    return dw(tabledivide64(numer, ebx));
117
}
118
#endif
119
 
4715 terminx 120
#define EDUKE32_SCALER_PRAGMA(a)                                                                                       \
121
    static inline int32_t divscale##a(int32_t eax, int32_t ebx) { return divscale(eax, ebx, a); }
4692 terminx 122
EDUKE32_GENERATE_PRAGMAS EDUKE32_SCALER_PRAGMA(32)
123
#undef EDUKE32_SCALER_PRAGMA
1492 terminx 124
 
4658 terminx 125
static inline int32_t scale(int32_t eax, int32_t edx, int32_t ecx)
126
{
127
    const int64_t numer = qw(eax) * edx;
128
    return dw(tabledivide64(numer, ecx));
129
}
130
 
2621 helixhorne 131
#if defined(__GNUC__) && defined(GEKKO)
5 Plagman 132
 
2621 helixhorne 133
// GCC Inline Assembler version (PowerPC)
4601 terminx 134
#include "pragmas_ppc.h"
2621 helixhorne 135
 
136
#elif defined(__GNUC__) && defined(__i386__) && !defined(NOASM)
137
 
138
// GCC Inline Assembler version (x86)
4601 terminx 139
#include "pragmas_x86_gcc.h"
5 Plagman 140
 
4715 terminx 141
#elif defined(_MSC_VER) && !defined(NOASM)  // __GNUC__
5 Plagman 142
 
143
// Microsoft C inline assembler
4601 terminx 144
#include "pragmas_x86_msvc.h"
5 Plagman 145
 
4715 terminx 146
#elif defined(__arm__)  // _MSC_VER
5 Plagman 147
 
4601 terminx 148
// GCC Inline Assembler version (ARM)
149
#include "pragmas_arm.h"
5 Plagman 150
 
4601 terminx 151
#else
5 Plagman 152
 
194 terminx 153
//
154
// Generic C
155
//
5 Plagman 156
 
4715 terminx 157
#define EDUKE32_SCALER_PRAGMA(a)                                                                                       \
158
    static inline int32_t mulscale##a(int32_t eax, int32_t edx) { return dw((qw(eax) * qw(edx)) >> by(a)); }           \
159
                                                                                                                       \
160
    static inline int32_t dmulscale##a(int32_t eax, int32_t edx, int32_t esi, int32_t edi)                             \
161
    {                                                                                                                  \
162
        return dw(((qw(eax) * qw(edx)) + (qw(esi) * qw(edi))) >> by(a));                                               \
163
    }
194 terminx 164
 
4715 terminx 165
 
4692 terminx 166
EDUKE32_GENERATE_PRAGMAS EDUKE32_SCALER_PRAGMA(32)
194 terminx 167
 
4692 terminx 168
#undef EDUKE32_SCALER_PRAGMA
4601 terminx 169
 
4715 terminx 170
static inline void swapchar(void *a, void *b)
171
{
172
    char t = *((char *)b);
173
    *((char *)b) = *((char *)a);
174
    *((char *)a) = t;
175
}
176
static inline void swapchar2(void *a, void *b, int32_t s)
177
{
178
    swapchar(a, b);
179
    swapchar((char *)a + 1, (char *)b + s);
180
}
181
static inline void swapshort(void *a, void *b)
182
{
183
    int16_t t = *((int16_t *)b);
184
    *((int16_t *)b) = *((int16_t *)a);
185
    *((int16_t *)a) = t;
186
}
187
static inline void swaplong(void *a, void *b)
188
{
189
    int32_t t = *((int32_t *)b);
190
    *((int32_t *)b) = *((int32_t *)a);
191
    *((int32_t *)a) = t;
192
}
193
static inline void swapfloat(void *a, void *b)
194
{
195
    float t = *((float *)b);
196
    *((float *)b) = *((float *)a);
197
    *((float *)a) = t;
198
}
199
static inline void swap64bit(void *a, void *b)
200
{
5073 terminx 201
    uint64_t t = *((uint64_t *)b);
202
    *((uint64_t *)b) = *((uint64_t *)a);
203
    *((uint64_t *)a) = t;
4715 terminx 204
}
194 terminx 205
 
4715 terminx 206
static inline char readpixel(void *s) { return (*((char *)(s))); }
207
static inline void drawpixel(void *s, char a) { *((char *)(s)) = a; }
194 terminx 208
 
4715 terminx 209
static inline int32_t klabs(int32_t a)
210
{
211
    const uint32_t m = a >> (sizeof(int) * CHAR_BIT - 1);
212
    return (a ^ m) - m;
213
}
214
static inline int32_t ksgn(int32_t a) { return (a > 0) - (a < 0); }
194 terminx 215
 
4604 terminx 216
static inline int32_t mulscale(int32_t eax, int32_t edx, int32_t ecx) { return dw((qw(eax) * edx) >> by(ecx)); }
4715 terminx 217
static inline int32_t dmulscale(int32_t eax, int32_t edx, int32_t esi, int32_t edi, int32_t ecx)
218
{
219
    return dw(((qw(eax) * edx) + (qw(esi) * edi)) >> by(ecx));
220
}
194 terminx 221
 
4715 terminx 222
void qinterpolatedown16(intptr_t bufptr, int32_t num, int32_t val, int32_t add);
223
void qinterpolatedown16short(intptr_t bufptr, int32_t num, int32_t val, int32_t add);
194 terminx 224
 
4715 terminx 225
void clearbuf(void *d, int32_t c, int32_t a);
226
void copybuf(const void *s, void *d, int32_t c);
227
void swapbuf4(void *a, void *b, int32_t c);
194 terminx 228
 
1205 terminx 229
void clearbufbyte(void *D, int32_t c, int32_t a);
2361 helixhorne 230
void copybufbyte(const void *S, void *D, int32_t c);
231
void copybufreverse(const void *S, void *D, int32_t c);
194 terminx 232
 
4661 terminx 233
static inline int32_t krecipasm(int32_t i)
234
{
235
    // Ken did this
4715 terminx 236
    float f = (float)i;
237
    i = *(int32_t *)&f;
238
    return ((reciptable[(i >> 12) & 2047] >> (((i - 0x3f800000) >> 23) & 31)) ^ (i >> 31));
4661 terminx 239
}
240
 
5 Plagman 241
#endif
242
 
4601 terminx 243
#undef qw
244
#undef dw
245
#undef wo
246
#undef by
247
 
4364 helixhorne 248
static inline void swapbufreverse(void *s, void *d, int32_t c)
249
{
4715 terminx 250
    uint8_t *src = (uint8_t *)s, *dst = (uint8_t *)d;
5009 helixhorne 251
    Bassert(c >= 4);
252
 
4658 terminx 253
    do
254
    {
255
        swapchar(dst, src);
4715 terminx 256
        swapchar(dst + 1, src - 1);
257
        swapchar(dst + 2, src - 2);
258
        swapchar(dst + 3, src - 3);
4658 terminx 259
        dst += 4, src -= 4;
5009 helixhorne 260
    } while ((c -= 4) > 4);
261
 
262
    while (c--)
263
        swapchar(dst++, src--);
4364 helixhorne 264
}
265
 
4766 hendricks2 266
#ifdef __cplusplus
201 terminx 267
}
268
#endif
269
 
4747 terminx 270
#endif  // pragmas_h_