Subversion Repositories eduke32

Rev

Rev 4363 | 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
 
1205 terminx 174
void clearbufbyte(void *D, int32_t c, int32_t a)
5 Plagman 175
{
584 terminx 176
    ASM(
109 terminx 177
        "cmpl $4, %%ecx\n\t"
178
        "jae 1f\n\t"
179
        "testb $1, %%cl\n\t"
180
        "jz 0f\n\t"                     // jz preskip
181
        "stosb\n\t"
182
        "0:\n\t"                        // preskip:
183
        "shrl $1, %%ecx\n\t"
184
        "rep\n\t"
185
        "stosw\n\t"
186
        "jmp 5f\n\t"                    // jmp endit
187
        "1:\n\t"                        // intcopy:
188
        "testl $1, %%edi\n\t"
189
        "jz 2f\n\t"                     // jz skip1
190
        "stosb\n\t"
191
        "decl %%ecx\n\t"
192
        "2:\n\t"                        // skip1:
193
        "testl $2, %%edi\n\t"
194
        "jz 3f\n\t"                     // jz skip2
195
        "stosw\n\t"
196
        "subl $2, %%ecx\n\t"
197
        "3:\n\t"                        // skip2:
198
        "movl %%ecx, %%ebx\n\t"
199
        "shrl $2, %%ecx\n\t"
200
        "rep\n\t"
201
        "stosl\n\t"
202
        "testb $2, %%bl\n\t"
203
        "jz 4f\n\t"                     // jz skip3
204
        "stosw\n\t"
205
        "4:\n\t"                        // skip3:
206
        "testb $1, %%bl\n\t"
207
        "jz 5f\n\t"                     // jz endit
208
        "stosb\n\t"
209
        "5:"                            // endit
584 terminx 210
    : "+D"(D), "+c"(c), "+a"(a) :
1762 terminx 211
            : "ebx", "memory", "cc"
212
        );
5 Plagman 213
}
214
 
2361 helixhorne 215
void copybufbyte(const void *S, void *D, int32_t c)
5 Plagman 216
{
584 terminx 217
    ASM(
109 terminx 218
        "cmpl $4, %%ecx\n\t"            // cmp ecx, 4
219
        "jae 1f\n\t"
220
        "testb $1, %%cl\n\t"            // test cl, 1
221
        "jz 0f\n\t"
222
        "movsb\n\t"
223
        "0:\n\t"                        // preskip:
224
        "shrl $1, %%ecx\n\t"            // shr ecx, 1
225
        "rep\n\t"
226
        "movsw\n\t"
227
        "jmp 5f\n\t"
228
        "1:\n\t"                        // intcopy:
229
        "testl $1, %%edi\n\t"           // test edi, 1
230
        "jz 2f\n\t"
231
        "movsb\n\t"
232
        "decl %%ecx\n\t"
233
        "2:\n\t"                        // skip1:
234
        "testl $2, %%edi\n\t"           // test edi, 2
235
        "jz 3f\n\t"
236
        "movsw\n\t"
237
        "subl $2, %%ecx\n\t"            // sub ecx, 2
238
        "3:\n\t"                        // skip2:
239
        "movl %%ecx, %%ebx\n\t"         // mov ebx, ecx
240
        "shrl $2, %%ecx\n\t"            // shr ecx ,2
241
        "rep\n\t"
242
        "movsl\n\t"
243
        "testb $2, %%bl\n\t"            // test bl, 2
244
        "jz 4f\n\t"
245
        "movsw\n\t"
246
        "4:\n\t"                        // skip3:
247
        "testb $1, %%bl\n\t"            // test bl, 1
248
        "jz 5f\n\t"
249
        "movsb\n\t"
250
        "5:"                            // endit:
584 terminx 251
    : "+c"(c), "+S"(S), "+D"(D) :
1762 terminx 252
            : "ebx", "memory", "cc"
253
        );
5 Plagman 254
}
255
 
2361 helixhorne 256
void copybufreverse(const void *S, void *D, int32_t c)
5 Plagman 257
{
584 terminx 258
    ASM(
109 terminx 259
        "shrl $1, %%ecx\n\t"
260
        "jnc 0f\n\t"            // jnc skipit1
261
        "movb (%%esi), %%al\n\t"
262
        "decl %%esi\n\t"
263
        "movb %%al, (%%edi)\n\t"
264
        "incl %%edi\n\t"
265
        "0:\n\t"                // skipit1:
266
        "shrl $1, %%ecx\n\t"
267
        "jnc 1f\n\t"            // jnc skipit2
268
        "movw -1(%%esi), %%ax\n\t"
269
        "subl $2, %%esi\n\t"
270
        "rorw $8, %%ax\n\t"
271
        "movw %%ax, (%%edi)\n\t"
272
        "addl $2, %%edi\n\t"
273
        "1:\n\t"                // skipit2
274
        "testl %%ecx, %%ecx\n\t"
275
        "jz 3f\n\t"             // jz endloop
276
        "2:\n\t"                // begloop
277
        "movl -3(%%esi), %%eax\n\t"
278
        "subl $4, %%esi\n\t"
279
        "bswapl %%eax\n\t"
280
        "movl %%eax, (%%edi)\n\t"
281
        "addl $4, %%edi\n\t"
282
        "decl %%ecx\n\t"
283
        "jnz 2b\n\t"            // jnz begloop
284
        "3:"
584 terminx 285
    : "+S"(S), "+D"(D), "+c"(c) :
1762 terminx 286
            : "eax", "memory", "cc"
287
        );
5 Plagman 288
}
289
 
1454 terminx 290
#elif defined(_MSC_VER) && !defined(NOASM)              // __GNUC__ && __i386__
5 Plagman 291
 
292
//
293
// Microsoft C Inline Assembler version
294
//
295
 
296
#else                           // _MSC_VER
297
 
194 terminx 298
//
299
// Generic C version
300
//
5 Plagman 301
 
1205 terminx 302
void qinterpolatedown16(intptr_t bufptr, int32_t num, int32_t val, int32_t add)
584 terminx 303
{
304
    // gee, I wonder who could have provided this...
1205 terminx 305
    int32_t i, *lptr = (int32_t *)bufptr;
1229 terminx 306
    for (i=0; i<num; i++) { lptr[i] = (val>>16); val += add; }
194 terminx 307
}
308
 
1205 terminx 309
void qinterpolatedown16short(intptr_t bufptr, int32_t num, int32_t val, int32_t add)
584 terminx 310
{
311
    // ...maybe the same person who provided this too?
1205 terminx 312
    int32_t i; int16_t *sptr = (int16_t *)bufptr;
1229 terminx 313
    for (i=0; i<num; i++) { sptr[i] = (int16_t)(val>>16); val += add; }
194 terminx 314
}
315
 
1205 terminx 316
void clearbuf(void *d, int32_t c, int32_t a)
194 terminx 317
{
3177 helixhorne 318
    int32_t *p = (int32_t *)d;
2361 helixhorne 319
 
194 terminx 320
    while ((c--) > 0) *(p++) = a;
321
}
322
 
2361 helixhorne 323
void copybuf(const void *s, void *d, int32_t c)
194 terminx 324
{
3177 helixhorne 325
    const int32_t *p = (const int32_t *)s;
2361 helixhorne 326
    int32_t *q = (int32_t *)d;
327
 
194 terminx 328
    while ((c--) > 0) *(q++) = *(p++);
329
}
330
 
1205 terminx 331
void swapbuf4(void *a, void *b, int32_t c)
194 terminx 332
{
1762 terminx 333
    int32_t *p = (int32_t *)a, *q = (int32_t *)b;
1205 terminx 334
    int32_t x, y;
584 terminx 335
    while ((c--) > 0)
336
    {
194 terminx 337
        x = *q;
338
        y = *p;
339
        *(q++) = y;
340
        *(p++) = x;
341
    }
342
}
343
 
1205 terminx 344
void clearbufbyte(void *D, int32_t c, int32_t a)
584 terminx 345
{
346
    // Cringe City
1762 terminx 347
    char *p = (char *)D;
3178 helixhorne 348
    int32_t m[4] = { 0xffl,0xff00l,0xff0000l,(int32_t)0xff000000l };
1205 terminx 349
    int32_t n[4] = { 0,8,16,24 };
350
    int32_t z=0;
584 terminx 351
    while ((c--) > 0)
352
    {
1205 terminx 353
        *(p++) = (uint8_t)((a & m[z])>>n[z]);
194 terminx 354
        z=(z+1)&3;
355
    }
356
}
357
 
2361 helixhorne 358
void copybufbyte(const void *S, void *D, int32_t c)
194 terminx 359
{
3177 helixhorne 360
    const char *p = (const char *)S;
361
    char *q = (char *)D;
2361 helixhorne 362
 
331 terminx 363
    while ((c--) > 0) *(q++) = *(p++);
194 terminx 364
}
365
 
4363 helixhorne 366
 
367
// copybufreverse() is a special case: use the assembly version for GCC on x86
368
// *and* x86_64, and the C version otherwise.
369
// XXX: we don't honor NOASM in the x86_64 case.
370
 
371
#if defined(__GNUC__) && defined(__x86_64__)
372
// NOTE: Almost CODEDUP from x86 GCC assembly version, except that
373
// - %%esi -> %%rsi
374
// - %%edi -> %%rdi
375
// - (dec,inc,sub,add)l suffix removed where necessary
2361 helixhorne 376
void copybufreverse(const void *S, void *D, int32_t c)
194 terminx 377
{
4363 helixhorne 378
    __asm__ __volatile__(
379
        "shrl $1, %%ecx\n\t"
380
        "jnc 0f\n\t"            // jnc skipit1
381
        "movb (%%rsi), %%al\n\t"
382
        "dec %%rsi\n\t"
383
        "movb %%al, (%%rdi)\n\t"
384
        "inc %%rdi\n\t"
385
        "0:\n\t"                // skipit1:
386
        "shrl $1, %%ecx\n\t"
387
        "jnc 1f\n\t"            // jnc skipit2
388
        "movw -1(%%rsi), %%ax\n\t"
389
        "sub $2, %%rsi\n\t"
390
        "rorw $8, %%ax\n\t"
391
        "movw %%ax, (%%rdi)\n\t"
392
        "add $2, %%rdi\n\t"
393
        "1:\n\t"                // skipit2
394
        "testl %%ecx, %%ecx\n\t"
395
        "jz 3f\n\t"             // jz endloop
396
        "2:\n\t"                // begloop
397
        "movl -3(%%rsi), %%eax\n\t"
398
        "sub $4, %%rsi\n\t"
399
        "bswapl %%eax\n\t"
400
        "movl %%eax, (%%rdi)\n\t"
401
        "add $4, %%rdi\n\t"
402
        "decl %%ecx\n\t"
403
        "jnz 2b\n\t"            // jnz begloop
404
        "3:"
405
    : "+S"(S), "+D"(D), "+c"(c) :
406
            : "eax", "memory", "cc"
407
        );
408
}
409
#else
410
void copybufreverse(const void *S, void *D, int32_t c)
411
{
3177 helixhorne 412
    const char *p = (const char *)S;
413
    char *q = (char *)D;
2361 helixhorne 414
 
331 terminx 415
    while ((c--) > 0) *(q++) = *(p--);
194 terminx 416
}
5 Plagman 417
#endif
418
 
419
 
4363 helixhorne 420
#endif