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