Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
5 Plagman 1
// Function-wrapped Watcom pragmas
2456 hendricks2 2
// by Jonathon Fowler (jf@jonof.id.au)
5 Plagman 3
//
4
// These functions represent some of the more longer-winded pragmas
5
// from the original pragmas.h wrapped into functions for easier
6
// use since many jumps and whatnot make it harder to write macro-
7
// inline versions. I'll eventually convert these to macro-inline
8
// equivalents.         --Jonathon
9
 
10
//#include "pragmas.h"
11
#include "compat.h"
12
 
1205 terminx 13
int32_t dmval;
5 Plagman 14
 
2621 helixhorne 15
#if defined(__GNUC__) && defined(GEKKO)
5 Plagman 16
 
2621 helixhorne 17
// naked function (no prolog/epilog)
4647 hendricks2 18
#pragma GCC diagnostic push
19
#pragma GCC diagnostic ignored "-Wunused-parameter"
20
#pragma GCC diagnostic ignored "-Wreturn-type"
21
int32_t scale(int32_t a, int32_t d, int32_t c) ATTRIBUTE((naked));
2621 helixhorne 22
int32_t scale(int32_t a, int32_t d, int32_t c)
23
{
24
//      return ((int64_t)a * d) / c;
25
 
26
        __asm__ __volatile__ (
27
                " mullw   6, 3, 4\n"
28
                " mulhw   4, 3, 4\n"
29
                " mr      3, 6\n"
30
 
31
                " srawi.  0, 5, 31\n"
32
                " cmpwi cr1, 4, 0\n"
33
                " crxor   7, 0, 4\n"
34
 
35
                " xor     5, 0, 5\n"
36
                " subf.   5, 0, 5\n"
37
 
38
                " beq     DivByZero\n"
39
                " bge   cr1, Div64Common\n"
40
 
41
                " subfic  3, 3, 0\n"
42
                " subfze  4, 4\n"
43
 
44
                "Div64Common:\n"
45
                " cmplw   4, 5\n"
46
 
47
                " cntlzw  6, 5\n"
48
                " xor     4, 4, 3\n"
49
                " slw     5, 5, 6\n"
50
                " rotlw   4, 4, 6\n"
51
                " slw     3, 3, 6\n"
52
                " li      7, 2\n"
53
                " xor     4, 4, 3\n"
54
 
55
                " bge DivOverflow\n"
56
                " mtctr   7\n"
57
 
58
                "Div64Compute:\n"
59
                " srwi    6, 5, 16\n"
60
                " divwu   7, 4, 6\n"
61
                " mullw   6, 7, 6\n"
62
                " subf    4, 6, 4\n"
63
                " slwi    4, 4, 16\n"
64
                " inslwi  4, 3, 16, 16\n"
65
                " slwi    3, 3, 16\n"
66
                " clrlwi  6, 5, 16\n"
67
                " mullw   6, 7, 6\n"
68
                " subfc   4, 6, 4\n"
69
                " subfe.  6, 6, 6\n"
70
                " add     3, 3, 7\n"
71
                " bge Div64Done\n"
72
                "Div64Correct:\n"
73
                " addc    4, 4, 5\n"
74
                " addze.  6, 6\n"
75
                " subi    3, 3, 1\n"
76
                " blt     Div64Correct\n"
77
 
78
                "Div64Done:\n"
79
                " bdnz    Div64Compute\n"
80
 
81
                " cmpwi   3, 0\n"
82
                " bso   cr1, Div64QuotientNeg\n"
83
 
84
                " blt     DivOverflow\n"
85
                " blr\n"
86
 
87
                "Div64QuotientNeg:\n"
88
                " neg.    3, 3\n"
89
                " blelr\n"
90
 
91
                "DivOverflow:\n"
92
                " cror    4, 7, 7\n"
93
 
94
                "DivByZero:\n"
95
                " lis     3, 0x8000\n"
96
                " bltlr cr1\n"
97
                " subi    3, 3, 1\n"
98
                " blr\n"
99
        );
100
}
4647 hendricks2 101
#pragma GCC diagnostic pop
2621 helixhorne 102
 
103
void clearbufbyte(void *d, int32_t c, int32_t a)
104
{
105
        if (a==0) {
106
                uint8_t *dd = (uint8_t*)d;
107
                int32_t align = (32 - (int32_t)d) & 31;
108
 
109
                if (align && c >= align) {
110
                        uint32_t izero = 0;
111
                        double fzero = 0;
112
                        c -= align;
113
 
114
                        if (align&1) {
115
                                *dd = izero;
116
                                dd += 1;
117
                        }
118
                        if (align&2) {
119
                                *(uint16_t*)dd = izero;
120
                                dd += 2;
121
                        }
122
                        if (align&4) {
123
                                *(uint32_t*)dd = izero;
124
                                dd += 4;
125
                        }
126
                        if (align&8) {
127
                                *(double*)dd = fzero;
128
                                dd += 8;
129
                        }
130
                        if (align&16) {
131
                                *(double*)dd = fzero;
132
                                *(double*)(dd+8) = fzero;
133
                                dd += 16;
134
                        }
135
                }
136
                align = c >> 5;
137
                while (align) {
138
                        __asm__ (
139
                                " dcbz  0, %0\n"
140
                                " addi %0, %0, 32\n"
141
                                : "+r"(dd)
142
                                :
143
                                : "memory"
144
                        );
145
                        align--;
146
                }
147
                if ((c &= 31)) {
148
                        while (c--) {
149
                                *dd++ = 0;
150
                        }
151
                }
152
                return;
153
        }
154
        __asm__ __volatile__ (
155
                " add    %1, %1, %2\n"
156
                " neg.   %2, %2\n"
157
                " beq 2f\n"
158
                "1:\n"
159
                " stbx   %0, %1, %2\n"
160
                " addic. %2, %2, 1\n"
161
                " rotrwi %0, %0, 8\n"
162
                " bne 1b\n"
163
                "2:\n"
164
                : "+r"(a), "+b"(d), "+r"(c)
165
                :
166
                : "cc", "xer", "memory"
167
        );
168
}
169
 
170
#elif defined(__GNUC__) && defined(__i386__) && !defined(NOASM) // NOASM
171
 
5 Plagman 172
//
173
// GCC Inline Assembler version
174
//
175
 
176
#define ASM __asm__ __volatile__
177
 
1205 terminx 178
void clearbufbyte(void *D, int32_t c, int32_t a)
5 Plagman 179
{
584 terminx 180
    ASM(
109 terminx 181
        "cmpl $4, %%ecx\n\t"
182
        "jae 1f\n\t"
183
        "testb $1, %%cl\n\t"
184
        "jz 0f\n\t"                     // jz preskip
185
        "stosb\n\t"
186
        "0:\n\t"                        // preskip:
187
        "shrl $1, %%ecx\n\t"
188
        "rep\n\t"
189
        "stosw\n\t"
190
        "jmp 5f\n\t"                    // jmp endit
191
        "1:\n\t"                        // intcopy:
192
        "testl $1, %%edi\n\t"
193
        "jz 2f\n\t"                     // jz skip1
194
        "stosb\n\t"
195
        "decl %%ecx\n\t"
196
        "2:\n\t"                        // skip1:
197
        "testl $2, %%edi\n\t"
198
        "jz 3f\n\t"                     // jz skip2
199
        "stosw\n\t"
200
        "subl $2, %%ecx\n\t"
201
        "3:\n\t"                        // skip2:
202
        "movl %%ecx, %%ebx\n\t"
203
        "shrl $2, %%ecx\n\t"
204
        "rep\n\t"
205
        "stosl\n\t"
206
        "testb $2, %%bl\n\t"
207
        "jz 4f\n\t"                     // jz skip3
208
        "stosw\n\t"
209
        "4:\n\t"                        // skip3:
210
        "testb $1, %%bl\n\t"
211
        "jz 5f\n\t"                     // jz endit
212
        "stosb\n\t"
213
        "5:"                            // endit
584 terminx 214
    : "+D"(D), "+c"(c), "+a"(a) :
1762 terminx 215
            : "ebx", "memory", "cc"
216
        );
5 Plagman 217
}
218
 
2361 helixhorne 219
void copybufbyte(const void *S, void *D, int32_t c)
5 Plagman 220
{
584 terminx 221
    ASM(
109 terminx 222
        "cmpl $4, %%ecx\n\t"            // cmp ecx, 4
223
        "jae 1f\n\t"
224
        "testb $1, %%cl\n\t"            // test cl, 1
225
        "jz 0f\n\t"
226
        "movsb\n\t"
227
        "0:\n\t"                        // preskip:
228
        "shrl $1, %%ecx\n\t"            // shr ecx, 1
229
        "rep\n\t"
230
        "movsw\n\t"
231
        "jmp 5f\n\t"
232
        "1:\n\t"                        // intcopy:
233
        "testl $1, %%edi\n\t"           // test edi, 1
234
        "jz 2f\n\t"
235
        "movsb\n\t"
236
        "decl %%ecx\n\t"
237
        "2:\n\t"                        // skip1:
238
        "testl $2, %%edi\n\t"           // test edi, 2
239
        "jz 3f\n\t"
240
        "movsw\n\t"
241
        "subl $2, %%ecx\n\t"            // sub ecx, 2
242
        "3:\n\t"                        // skip2:
243
        "movl %%ecx, %%ebx\n\t"         // mov ebx, ecx
244
        "shrl $2, %%ecx\n\t"            // shr ecx ,2
245
        "rep\n\t"
246
        "movsl\n\t"
247
        "testb $2, %%bl\n\t"            // test bl, 2
248
        "jz 4f\n\t"
249
        "movsw\n\t"
250
        "4:\n\t"                        // skip3:
251
        "testb $1, %%bl\n\t"            // test bl, 1
252
        "jz 5f\n\t"
253
        "movsb\n\t"
254
        "5:"                            // endit:
584 terminx 255
    : "+c"(c), "+S"(S), "+D"(D) :
1762 terminx 256
            : "ebx", "memory", "cc"
257
        );
5 Plagman 258
}
259
 
2361 helixhorne 260
void copybufreverse(const void *S, void *D, int32_t c)
5 Plagman 261
{
584 terminx 262
    ASM(
109 terminx 263
        "shrl $1, %%ecx\n\t"
264
        "jnc 0f\n\t"            // jnc skipit1
265
        "movb (%%esi), %%al\n\t"
266
        "decl %%esi\n\t"
267
        "movb %%al, (%%edi)\n\t"
268
        "incl %%edi\n\t"
269
        "0:\n\t"                // skipit1:
270
        "shrl $1, %%ecx\n\t"
271
        "jnc 1f\n\t"            // jnc skipit2
272
        "movw -1(%%esi), %%ax\n\t"
273
        "subl $2, %%esi\n\t"
274
        "rorw $8, %%ax\n\t"
275
        "movw %%ax, (%%edi)\n\t"
276
        "addl $2, %%edi\n\t"
277
        "1:\n\t"                // skipit2
278
        "testl %%ecx, %%ecx\n\t"
279
        "jz 3f\n\t"             // jz endloop
280
        "2:\n\t"                // begloop
281
        "movl -3(%%esi), %%eax\n\t"
282
        "subl $4, %%esi\n\t"
283
        "bswapl %%eax\n\t"
284
        "movl %%eax, (%%edi)\n\t"
285
        "addl $4, %%edi\n\t"
286
        "decl %%ecx\n\t"
287
        "jnz 2b\n\t"            // jnz begloop
288
        "3:"
584 terminx 289
    : "+S"(S), "+D"(D), "+c"(c) :
1762 terminx 290
            : "eax", "memory", "cc"
291
        );
5 Plagman 292
}
293
 
1454 terminx 294
#elif defined(_MSC_VER) && !defined(NOASM)              // __GNUC__ && __i386__
5 Plagman 295
 
296
//
297
// Microsoft C Inline Assembler version
298
//
299
 
300
#else                           // _MSC_VER
301
 
194 terminx 302
//
303
// Generic C version
304
//
5 Plagman 305
 
1205 terminx 306
void qinterpolatedown16(intptr_t bufptr, int32_t num, int32_t val, int32_t add)
584 terminx 307
{
308
    // gee, I wonder who could have provided this...
1205 terminx 309
    int32_t i, *lptr = (int32_t *)bufptr;
1229 terminx 310
    for (i=0; i<num; i++) { lptr[i] = (val>>16); val += add; }
194 terminx 311
}
312
 
1205 terminx 313
void qinterpolatedown16short(intptr_t bufptr, int32_t num, int32_t val, int32_t add)
584 terminx 314
{
315
    // ...maybe the same person who provided this too?
1205 terminx 316
    int32_t i; int16_t *sptr = (int16_t *)bufptr;
1229 terminx 317
    for (i=0; i<num; i++) { sptr[i] = (int16_t)(val>>16); val += add; }
194 terminx 318
}
319
 
1205 terminx 320
void clearbuf(void *d, int32_t c, int32_t a)
194 terminx 321
{
3177 helixhorne 322
    int32_t *p = (int32_t *)d;
2361 helixhorne 323
 
194 terminx 324
    while ((c--) > 0) *(p++) = a;
325
}
326
 
2361 helixhorne 327
void copybuf(const void *s, void *d, int32_t c)
194 terminx 328
{
3177 helixhorne 329
    const int32_t *p = (const int32_t *)s;
2361 helixhorne 330
    int32_t *q = (int32_t *)d;
331
 
194 terminx 332
    while ((c--) > 0) *(q++) = *(p++);
333
}
334
 
1205 terminx 335
void swapbuf4(void *a, void *b, int32_t c)
194 terminx 336
{
1762 terminx 337
    int32_t *p = (int32_t *)a, *q = (int32_t *)b;
1205 terminx 338
    int32_t x, y;
584 terminx 339
    while ((c--) > 0)
340
    {
194 terminx 341
        x = *q;
342
        y = *p;
343
        *(q++) = y;
344
        *(p++) = x;
345
    }
346
}
347
 
1205 terminx 348
void clearbufbyte(void *D, int32_t c, int32_t a)
584 terminx 349
{
350
    // Cringe City
1762 terminx 351
    char *p = (char *)D;
3178 helixhorne 352
    int32_t m[4] = { 0xffl,0xff00l,0xff0000l,(int32_t)0xff000000l };
1205 terminx 353
    int32_t n[4] = { 0,8,16,24 };
354
    int32_t z=0;
584 terminx 355
    while ((c--) > 0)
356
    {
1205 terminx 357
        *(p++) = (uint8_t)((a & m[z])>>n[z]);
194 terminx 358
        z=(z+1)&3;
359
    }
360
}
361
 
2361 helixhorne 362
void copybufbyte(const void *S, void *D, int32_t c)
194 terminx 363
{
3177 helixhorne 364
    const char *p = (const char *)S;
365
    char *q = (char *)D;
2361 helixhorne 366
 
331 terminx 367
    while ((c--) > 0) *(q++) = *(p++);
194 terminx 368
}
369
 
4363 helixhorne 370
 
371
// copybufreverse() is a special case: use the assembly version for GCC on x86
372
// *and* x86_64, and the C version otherwise.
373
// XXX: we don't honor NOASM in the x86_64 case.
374
 
375
#if defined(__GNUC__) && defined(__x86_64__)
376
// NOTE: Almost CODEDUP from x86 GCC assembly version, except that
377
// - %%esi -> %%rsi
378
// - %%edi -> %%rdi
379
// - (dec,inc,sub,add)l suffix removed where necessary
2361 helixhorne 380
void copybufreverse(const void *S, void *D, int32_t c)
194 terminx 381
{
4363 helixhorne 382
    __asm__ __volatile__(
383
        "shrl $1, %%ecx\n\t"
384
        "jnc 0f\n\t"            // jnc skipit1
385
        "movb (%%rsi), %%al\n\t"
386
        "dec %%rsi\n\t"
387
        "movb %%al, (%%rdi)\n\t"
388
        "inc %%rdi\n\t"
389
        "0:\n\t"                // skipit1:
390
        "shrl $1, %%ecx\n\t"
391
        "jnc 1f\n\t"            // jnc skipit2
392
        "movw -1(%%rsi), %%ax\n\t"
393
        "sub $2, %%rsi\n\t"
394
        "rorw $8, %%ax\n\t"
395
        "movw %%ax, (%%rdi)\n\t"
396
        "add $2, %%rdi\n\t"
397
        "1:\n\t"                // skipit2
398
        "testl %%ecx, %%ecx\n\t"
399
        "jz 3f\n\t"             // jz endloop
400
        "2:\n\t"                // begloop
401
        "movl -3(%%rsi), %%eax\n\t"
402
        "sub $4, %%rsi\n\t"
403
        "bswapl %%eax\n\t"
404
        "movl %%eax, (%%rdi)\n\t"
405
        "add $4, %%rdi\n\t"
406
        "decl %%ecx\n\t"
407
        "jnz 2b\n\t"            // jnz begloop
408
        "3:"
409
    : "+S"(S), "+D"(D), "+c"(c) :
410
            : "eax", "memory", "cc"
411
        );
412
}
413
#else
414
void copybufreverse(const void *S, void *D, int32_t c)
415
{
3177 helixhorne 416
    const char *p = (const char *)S;
417
    char *q = (char *)D;
2361 helixhorne 418
 
331 terminx 419
    while ((c--) > 0) *(q++) = *(p--);
194 terminx 420
}
5 Plagman 421
#endif
422
 
423
 
4363 helixhorne 424
#endif