This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[btb/d2x.git] / 2d / linear.h
1 #ifndef _LINEAR_H
2 #define _LINEAR_H
3
4 #ifndef NO_ASM
5 #ifdef __WATCOMC__
6 extern unsigned int gr_var_color;
7 extern unsigned int gr_var_bwidth;
8 extern unsigned char * gr_var_bitmap;
9
10 void gr_linear_stosd( void * source, unsigned char color, unsigned int nbytes);
11 void gr_linear_line( int x0, int y0, int x1, int y1);
12 void gr_update_buffer( void * sbuf1, void * sbuf2, void * dbuf, int size );
13
14 // This code aligns edi so that the destination is aligned to a dword boundry before rep movsd
15 void gr_linear_movsd(ubyte * src, ubyte * dest, unsigned int num_pixels );
16 #pragma aux gr_linear_movsd parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx] = \
17 " cld "                 \
18 " mov       ebx, ecx    "   \
19 " mov       eax, edi"   \
20 " and       eax, 011b"  \
21 " jz        d_aligned"  \
22 " mov       ecx, 4"     \
23 " sub       ecx, eax"   \
24 " sub       ebx, ecx"   \
25 " rep       movsb"      \
26 " d_aligned: "          \
27 " mov       ecx, ebx"   \
28 " shr       ecx, 2"     \
29 " rep   movsd"      \
30 " mov       ecx, ebx"   \
31 " and   ecx, 11b"   \
32 " rep   movsb";
33
34 void gr_linear_rep_movsdm(void * src, void * dest, unsigned int num_pixels );
35 #pragma aux gr_linear_rep_movsdm parm [esi] [edi] [ecx] modify exact [ecx esi edi eax] = \
36 "nextpixel:"                    \
37     "mov    al,[esi]"           \
38     "inc    esi"                    \
39     "cmp    al, 255"                \
40     "je skip_it"                \
41     "mov    [edi], al"          \
42 "skip_it:"                      \
43     "inc    edi"                    \
44     "dec    ecx"                    \
45     "jne    nextpixel";
46
47 void gr_linear_rep_movsdm_faded(void * src, void * dest, unsigned int num_pixels, ubyte fade_value );
48 #pragma aux gr_linear_rep_movsdm_faded parm [esi] [edi] [ecx] [ebx] modify exact [ecx esi edi eax ebx] = \
49 "  xor eax, eax"    \
50 "  mov ah, bl"  \
51 "nextpixel:"                    \
52     "mov    al,[esi]"           \
53     "inc    esi"                    \
54     "cmp    al, 255"                \
55     "je skip_it"                \
56     "movb  al, gr_fade_table[eax]"   \
57     "movb  [edi], al"          \
58 "skip_it:"                      \
59     "inc    edi"                    \
60     "dec    ecx"                    \
61     "jne    nextpixel";
62
63
64 void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, int num_dest_pixels );
65 #pragma aux gr_linear_rep_movsd_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx] = \
66     "shr    ecx, 1"             \
67     "jnc    nextpixel"          \
68     "mov    al, [esi]"          \
69     "mov    [edi], al"          \
70     "inc    esi"                    \
71     "inc    edi"                    \
72     "cmp    ecx, 0"             \
73     "je done"                   \
74 "nextpixel:"                    \
75     "mov    al,[esi]"           \
76     "mov    ah, al"             \
77     "mov    [edi], ax"          \
78     "inc    esi"                    \
79     "inc    edi"                    \
80     "inc    edi"                    \
81     "dec    ecx"                    \
82     "jne    nextpixel"          \
83 "done:"
84
85
86
87 void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize );
88 #pragma aux modex_copy_column parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = \
89 "nextpixel:"                            \
90     "mov    al,[esi]"           \
91     "add    esi, ebx"   \
92     "mov    [edi], al"  \
93     "add    edi, edx"   \
94     "dec    ecx"            \
95     "jne    nextpixel"  
96
97 void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize );
98 #pragma aux modex_copy_column_m parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = \
99 "nextpixel:"                            \
100     "mov    al,[esi]"           \
101     "add    esi, ebx"   \
102     "cmp    al, 255"        \
103     "je skip_itx"       \
104     "mov    [edi], al"  \
105 "skip_itx:"             \
106     "add    edi, edx"   \
107     "dec    ecx"            \
108     "jne    nextpixel"  
109
110 void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels );
111 #pragma aux modex_copy_scanline parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = \
112 "       mov ebx, ecx                "   \
113 "       and ebx, 11b                "   \
114 "       shr ecx, 2              "   \
115 "       cmp ecx, 0              "   \
116 "       je      no2group                "   \
117 "next4pixels:                       "   \
118 "       mov al, [esi+8]         "   \
119 "       mov ah, [esi+12]        "   \
120 "       shl eax, 16             "   \
121 "       mov al, [esi]           "   \
122 "       mov ah, [esi+4]         "   \
123 "       mov [edi], eax          "   \
124 "       add esi, 16             "   \
125 "       add edi, 4              "   \
126 "       dec ecx                 "   \
127 "       jne next4pixels         "   \
128 "no2group:                          "   \
129 "       cmp ebx, 0              "   \
130 "       je      done2                   "   \
131 "finishend:                         "   \
132 "       mov al, [esi]           "   \
133 "       add esi, 4              "   \
134 "       mov [edi], al           "   \
135 "       inc edi                 "   \
136 "       dec ebx                 "   \
137 "       jne finishend           "   \
138 "done2:                             ";
139
140 void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels );
141 #pragma aux modex_copy_scanline_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = \
142 "       mov ebx, ecx                "   \
143 "       and ebx, 11b                "   \
144 "       shr ecx, 2              "   \
145 "       cmp ecx, 0              "   \
146 "       je      no2group                "   \
147 "next4pixels:                       "   \
148 "       mov al, [esi+4]         "   \
149 "       mov ah, [esi+6]         "   \
150 "       shl eax, 16             "   \
151 "       mov al, [esi]           "   \
152 "       mov ah, [esi+2]         "   \
153 "       mov [edi], eax          "   \
154 "       add esi, 8              "   \
155 "       add edi, 4              "   \
156 "       dec ecx                 "   \
157 "       jne next4pixels         "   \
158 "no2group:                          "   \
159 "       cmp ebx, 0              "   \
160 "       je      done2                   "   \
161 "finishend:                         "   \
162 "       mov al, [esi]           "   \
163 "       add esi, 2              "   \
164 "       mov [edi], al           "   \
165 "       inc edi                 "   \
166 "       dec ebx                 "   \
167 "       jne finishend           "   \
168 "done2:                             ";
169
170 #elif defined __GNUC__
171 // This code aligns edi so that the destination is aligned to a dword boundry before rep movsd
172 inline void gr_linear_movsd(ubyte * src, ubyte * dest, unsigned int num_pixels ) {
173         int dummy[3];
174  __asm__ __volatile__ (
175 " cld;"
176 " movl      %%ecx, %%ebx;"
177 " movl      %%edi, %%eax;"
178 " andl      $3, %%eax;"
179 " jz        0f;"
180 " movl      $4, %%ecx;"
181 " subl      %%eax,%%ecx;"
182 " subl      %%ecx,%%ebx;"
183 " rep;      movsb;"
184 "0: ;"
185 " movl      %%ebx, %%ecx;"
186 " shrl      $2, %%ecx;"
187 " rep;      movsl;"
188 " movl      %%ebx, %%ecx;"
189 " andl      $3, %%ecx;"
190 " rep;      movsb"
191  : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2])
192  : "0" (src), "1" (dest), "2" (num_pixels)
193  :      "%eax", "%ebx");
194 }
195
196 static inline void gr_linear_rep_movsdm(void * src, void * dest, unsigned int num_pixels ) {
197         int dummy[3];
198  __asm__ __volatile__ (
199 "0: ;"
200 " movb  (%%esi), %%al;"
201 " incl  %%esi;"
202 " cmpb  $255, %%al;"
203 " je    1f;"
204 " movb  %%al,(%%edi);"
205 "1: ;"
206 " incl  %%edi;"
207 " decl  %%ecx;"
208 " jne   0b"
209  : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2])
210  : "0" (src), "1" (dest), "2" (num_pixels)
211  :      "%eax");
212 }
213
214 /* #pragma aux gr_linear_rep_movsdm_faded parm [esi] [edi] [ecx] [ebx] modify exact [ecx esi edi eax ebx] */
215 static inline void gr_linear_rep_movsdm_faded(void * src, void * dest, unsigned int num_pixels, ubyte fade_value ) {
216         int dummy[4];
217  __asm__ __volatile__ (
218 "  xorl   %%eax, %%eax;"
219 "  movb   %%bl, %%ah;"
220 "0:;"
221 "  movb   (%%esi), %%al;"
222 "  incl   %%esi;"
223 "  cmpb   $255, %%al;"
224 "  je 1f;"
225 #ifdef __linux__
226 "  movb   gr_fade_table(%%eax), %%al;"
227 #else
228 "  movb   _gr_fade_table(%%eax), %%al;"
229 #endif
230 "  movb   %%al, (%%edi);"
231 "1:"
232 "  incl   %%edi;"
233 "  decl   %%ecx;"
234 "  jne    0b"
235  : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2]), "=b" (dummy[3])
236  : "0" (src), "1" (dest), "2" (num_pixels), "3" (fade_value)
237  :      "%eax");
238 }
239
240 inline void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, unsigned int num_dest_pixels ) {
241 /* #pragma aux gr_linear_rep_movsd_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx] */
242         int dummy[3];
243  __asm__ __volatile__ (
244     "shrl   $1, %%ecx;"
245     "jnc    0f;"
246     "movb   (%%esi), %%al;"
247     "movb   %%al, (%%edi);"
248     "incl   %%esi;"
249     "incl   %%edi;"
250     "cmpl   $0, %%ecx;"
251     "je 1f;"
252 "0: ;"
253     "movb   (%%esi), %%al;"
254     "movb   %%al, %%ah;"
255     "movw   %%ax, (%%edi);"
256     "incl   %%esi;"
257     "incl   %%edi;"
258     "incl   %%edi;"
259     "decl   %%ecx;"
260     "jne    0b;"
261 "1:"
262  : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2])
263  : "0" (src), "1" (dest), "2" (num_dest_pixels)
264  :      "%eax");
265 }
266
267 static inline void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ) {
268 /*#pragma aux modex_copy_column parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = */
269  __asm__ __volatile__ (
270 "0: ;"
271     "movb   (%%esi), %%al;"
272     "addl   %%ebx, %%esi;"
273     "movb   %%al, (%%edi);"
274     "addl   %%edx, %%edi;"
275     "decl   %%ecx;"
276     "jne    0b"
277  : : "S" (src), "D" (dest), "c" (num_pixels), "b" (src_rowsize), "d" (dest_rowsize)
278  :      "%eax", "%ecx", "%esi", "%edi");
279 }
280
281 static inline void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ) {
282 /* #pragma aux modex_copy_column_m parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = */
283  int dummy[3];
284  __asm__ __volatile__ (
285 "0: ;"
286     "movb    (%%esi), %%al;"
287     "addl    %%ebx, %%esi;"
288     "cmpb    $255, %%al;"
289     "je 1f;"
290     "movb   %%al, (%%edi);"
291 "1: ;"
292     "addl   %%edx, %%edi;"
293     "decl   %%ecx;"
294     "jne    0b"
295  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
296  : "1" (src), "2" (dest), "0" (num_pixels), "b" (src_rowsize), "d" (dest_rowsize)
297  :      "%eax" );
298 }
299
300 static inline void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels ) {
301 /* #pragma aux modex_copy_scanline parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] */
302 int dummy[3];
303  __asm__ __volatile__ (
304 "       movl %%ecx, %%ebx;"
305 "       andl $3, %%ebx;"
306 "       shrl $2, %%ecx;"
307 "       cmpl $0, %%ecx;"
308 "       je   1f;"
309 "0: ;"
310 "       movb 8(%%esi), %%al;"
311 "       movb 12(%%esi), %%ah;"
312 "       shll $16, %%eax;"
313 "       movb (%%esi), %%al;"
314 "       movb 4(%%esi), %%ah;"
315 "       movl %%eax, (%%edi);"
316 "       addl $16, %%esi;"
317 "       addl $4, %%edi;"
318 "       decl %%ecx;"
319 "       jne 0b;"
320 "1: ;"
321 "       cmpl $0, %%ebx;"
322 "       je      3f;"
323 "2: ;"
324 "       movb (%%esi), %%al;"
325 "       addl $4, %%esi;"
326 "       movb %%al, (%%edi);"
327 "       incl %%edi;"
328 "       decl %%ebx;"
329 "       jne 2b;"
330 "3:"
331  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
332  : "1" (src), "2" (dest), "0" (npixels)
333  :      "%eax", "%ebx", "%edx" );
334 }
335
336 static inline void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels ) {
337 /* #pragma aux modex_copy_scanline_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = */
338 int dummy[3];
339  __asm__ __volatile__ (
340 "       movl %%ecx, %%ebx;"
341 "       andl $3, %%ebx;"
342 "       shrl $2, %%ecx;"
343 "       cmpl $0, %%ecx;"
344 "       je 1f;"
345 "0: ;"
346 "       movb 4(%%esi), %%al;"
347 "       movb 6(%%esi), %%ah;"
348 "       shll $16, %%eax;"
349 "       movb (%%esi), %%al;"
350 "       movb 2(%%esi), %%ah;"
351 "       movl %%eax, (%%edi);"
352 "       addl $8, %%esi;"
353 "       addl $4, %%edi;"
354 "       decl %%ecx;"
355 "       jne 0b;"
356 "1: ;"
357 "       cmp $0, %%ebx;"
358 "       je  3f;"
359 "2:"
360 "       movb (%%esi),%%al;"
361 "       addl $2, %%esi;"
362 "       movb %%al, (%%edi);"
363 "       incl %%edi;"
364 "       decl %%ebx;"
365 "       jne 2b;"
366 "3:"
367  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
368  : "1" (src), "2" (dest), "0" (npixels)
369  :      "%eax", "%ebx", "%edx" );
370 }
371 #elif defined _MSC_VER
372
373 extern unsigned int gr_var_color;
374 extern unsigned int gr_var_bwidth;
375 extern unsigned char * gr_var_bitmap;
376
377 void gr_linear_stosd( ubyte * source, unsigned char color, unsigned int nbytes);
378 void gr_linear_line( int x0, int y0, int x1, int y1);
379 void gr_update_buffer( void * sbuf1, void * sbuf2, void * dbuf, int size );
380
381 // This code aligns edi so that the destination is aligned to a dword boundry before rep movsd
382 __inline void gr_linear_movsd(ubyte * src, ubyte * dest, unsigned int num_pixels )
383 {
384  __asm {
385    mov esi, [src]
386    mov edi, [dest]
387    mov ecx, [num_pixels]
388    cld
389    mov ebx, ecx
390    mov eax, edi
391    and eax, 011b
392    jz d_aligned
393    mov ecx, 4
394    sub ecx, eax
395    sub ebx, ecx
396    rep movsb
397 d_aligned:
398    mov ecx, ebx
399    shr ecx, 2
400    rep movsd
401    mov ecx, ebx
402    and ecx, 11b
403    rep movsb
404  }
405 }
406
407 __inline void gr_linear_rep_movsdm(void * src, void * dest, unsigned int num_pixels )
408 {
409  __asm {
410   nextpixel:
411   mov esi, [src]
412   mov edi, [dest]
413   mov ecx, [num_pixels]
414   mov al,  [esi]
415   inc esi
416   cmp al,  255
417   je skip_it
418   mov [edi], al
419   skip_it:
420   inc edi
421   dec ecx
422   jne nextpixel
423  }
424 }
425
426 __inline void gr_linear_rep_movsdm_faded(void * src, void * dest, unsigned int num_pixels, ubyte fade_value )
427 {
428  __asm {
429   mov esi, [src]
430   mov edi, [dest]
431   mov ecx, [num_pixels]
432   movzx ebx, byte ptr [fade_value]
433   xor eax, eax
434   mov ah, bl
435   nextpixel:
436   mov al, [esi]
437   inc esi
438   cmp al, 255
439   je skip_it
440   mov al, gr_fade_table[eax]
441   mov [edi], al
442   skip_it:
443   inc edi
444   dec ecx
445   jne nextpixel
446  }
447 }
448
449 __inline void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, uint num_dest_pixels )
450 {
451  __asm {
452   mov esi, [src]
453   mov edi, [dest]
454   mov ecx, [num_dest_pixels]
455   shr ecx, 1
456   jnc nextpixel
457   mov al, [esi]
458   mov [edi], al
459   inc esi
460   inc edi
461   cmp ecx, 0
462   je done
463 nextpixel:
464   mov al, [esi]
465   mov ah, al
466   mov [edi], ax
467   inc esi
468   inc edi
469   inc edi
470   dec ecx
471   jne nextpixel
472 done:
473  }
474 }
475
476 #else
477 #define NO_ASM 1 // We really do want no assembler...
478
479 #endif
480 #endif // NO_ASM
481
482 #endif