Subversion Repositories eduke32

Rev

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