1 /**
2  ** memcopy.h ---- inline assembly memory copy macros -- GNU-C code
3  **
4  ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
5  ** [e-mail: csaba@vuse.vanderbilt.edu]
6  **
7  ** This file is part of the GRX graphics library.
8  **
9  ** The GRX graphics library is free software; you can redistribute it
10  ** and/or modify it under some conditions; see the "copying.grx" file
11  ** for details.
12  **
13  ** This library is distributed in the hope that it will be useful,
14  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  **
17  **/
18 
19 /* ================================================================ */
20 /* ==                     80386 FAMILY                           == */
21 /* ================================================================ */
22 #ifdef __i386__
23 
24 #ifndef MOV_INS
25 #include "gcc/asmsupp.h"
26 #endif
27 
28 #define __INLINE_386_ROWCOPY__(D,S,C,SIZE) ({                           \
29     __asm__ volatile(                                                   \
30 	" cld        \n"                                                 \
31 	" rep        \n"                                                 \
32 	" movs"#SIZE                                                     \
33 	: "=D" ((void *)(D)), "=S" ((void *)(S)), "=c" ((int)(C))       \
34 	: "0"  ((void *)(D)), "1"  ((void *)(S)), "2"  ((int)(C))       \
35 	: "memory"                                                      \
36     );                                                                  \
37 })
38 
39 #define __INLINE_STD_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)                   \
40 	__INLINE_386_ROWCOPY__(D,S,C,SIZE)
41 
42 #define __INLINE_386_G_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL) ({  \
43     register TYPE _scr_;                                                     \
44     __asm__ volatile(""                                                      \
45 	  "    incl    %2                           \n"                      \
46 	  "    shrl    $1,%2                        \n"                      \
47 	  "    jnc     1f                           \n"                      \
48 	  "    jmp     0f                           \n"                      \
49 	  "    .align 4,0x90                        \n"                      \
50 	  "0:  "#SIN""#SIZE"  "#SSEL"(%1),%3        \n"                      \
51 	  "    addl    %8,%1                        \n"                      \
52 	  "    "#DIN""#SIZE"   %3,"#DSEL"(%0)       \n"                      \
53 	  "    addl    %7,%0                        \n"                      \
54 	  "1:  "#SIN""#SIZE"  "#SSEL"(%1),%3        \n"                      \
55 	  "    addl    %8,%1                        \n"                      \
56 	  "    "#DIN""#SIZE"   %3,"#DSEL"(%0)       \n"                      \
57 	  "    addl    %7,%0                        \n"                      \
58 	  "    decl    %2                           \n"                      \
59 	  "    jne     0b"                                                   \
60 	  : "=r" ((void *)(DP)),"=r" ((void *)(SP)),"=r" ((int)(C)),         \
61 	    "=&q" ((TYPE)_scr_)                                              \
62 	  : "0"  ((void *)(DP)),"1"  ((void *)(SP)), "2" ((int)(C)),         \
63 	    "gn" ((int)(DS)), "gn" ((int)(SS))                               \
64 	  : "memory"                                                         \
65     );                                                                       \
66 })
67 
68 #define __INLINE_386_C_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,DINC,SINC) ({\
69     register TYPE _scr_;                                                     \
70     __asm__ volatile(""                                                      \
71 	  "    incl    %2                           \n"                      \
72 	  "    shrl    $1,%2                        \n"                      \
73 	  "    jnc     1f                           \n"                      \
74 	  "    jmp     0f                           \n"                      \
75 	  "    .align 4,0x90                        \n"                      \
76 	  "0:  "#SIN""#SIZE"  "#SSEL"(%1),%3        \n"                      \
77 	  "    " SINC "                             \n"                      \
78 	  "    "#DIN""#SIZE"   %3,"#DSEL"(%0)       \n"                      \
79 	  "    " DINC "                             \n"                      \
80 	  "1:  "#SIN""#SIZE"  "#SSEL"(%1),%3        \n"                      \
81 	  "    " SINC "                             \n"                      \
82 	  "    "#DIN""#SIZE"   %3,"#DSEL"(%0)       \n"                      \
83 	  "    " DINC "                             \n"                      \
84 	  "    decl    %2                           \n"                      \
85 	  "    jne     0b"                                                   \
86 	  : "=r" ((void *)(DP)),"=r" ((void *)(SP)),"=r" ((int)(C)),         \
87 	    "=&q" ((TYPE)_scr_)                                              \
88 	  : "0"  ((void *)(DP)),"1"  ((void *)(SP)), "2" ((int)(C))          \
89 	  : "memory"                                                         \
90     );                                                                       \
91 })
92 
93 #define __INLINE_386_C2_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,DINC) ({\
94     if( (SS) == 1 )                                                           \
95        __INLINE_386_C_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,DINC,"incl %1");\
96     else                                                                      \
97     if( (SS) == -1 )                                                          \
98        __INLINE_386_C_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,DINC,"decl %1");\
99     else                                                                      \
100     if( (SS) == 2 )                                                           \
101        __INLINE_386_C_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,DINC,"leal 2(%1),%1");\
102     else                                                                      \
103     if( (SS) == -2 )                                                          \
104        __INLINE_386_C_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,DINC,"leal -2(%1),%1");\
105     else                                                                      \
106     if( (SS) == 4 )                                                           \
107        __INLINE_386_C_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,DINC,"leal 4(%1),%1");\
108     else                                                                      \
109     if( (SS) == -4 )                                                          \
110        __INLINE_386_C_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,DINC,"leal -4(%1),%1");\
111     else                                                                      \
112        __INLINE_386_G_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL);      \
113 })
114 
115 #define __INLINE_386_C1_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL) ({  \
116     if( (DS) == 1 )                                                           \
117        __INLINE_386_C2_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,"incl %0");\
118     else                                                                      \
119     if( (DS) == -1 )                                                          \
120        __INLINE_386_C2_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,"decl %0");\
121     else                                                                      \
122     if( (DS) == 2 )                                                           \
123        __INLINE_386_C2_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,"leal 2(%0),%0");\
124     else                                                                      \
125     if( (DS) == -2 )                                                          \
126        __INLINE_386_C2_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,"leal -2(%0),%0");\
127     else                                                                      \
128     if( (DS) == 4 )                                                           \
129        __INLINE_386_C2_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,"leal 4(%0),%0");\
130     else                                                                      \
131     if( (DS) == -4 )                                                          \
132        __INLINE_386_C2_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL,"leal -4(%0),%0");\
133     else                                                                      \
134        __INLINE_386_G_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL);      \
135 })
136 
137 
138 #define __INLINE_386_COLCOPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL) ({  \
139     if(__builtin_constant_p(DS) && __builtin_constant_p(SS) )                 \
140        __INLINE_386_C1_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL);     \
141     else                                                                      \
142        __INLINE_386_G_COPY__(DP,DS,SP,SS,C,DIN,SIN,SIZE,TYPE,DSEL,SSEL);      \
143 })
144 
145 #define __INLINE_SEGSEG_ROWCOPY__(D,S,C,SZ,T,DS,SS)                           \
146 	__INLINE_386_COLCOPY__(D,CPSIZE_##SZ,S,CPSIZE_##SZ,C,mov,mov,SZ,T,DS,SS)
147 
148 /* memory -> memory copies */
149 #define __INLINE_STD_COLCOPY__(D,DSKP,S,SSKP,C,DM,SM,INS,SIZE,TYPE)           \
150 	__INLINE_386_COLCOPY__(D,DSKP,S,SSKP,C,INS,mov,SIZE,TYPE,,)
151 #ifdef  I386_GCC_FAR_MEMORY
152 /* memory -> video copies */
153 #define __INLINE_FAR_STD_COLCOPY__(DST,DSKP,SRC,SSKP,C,DM,SM,INS,SIZE,TYPE)   \
154 	__INLINE_386_COLCOPY__(DST,DSKP,SRC,SSKP,C,INS,mov,SIZE,TYPE,%%fs:,)
155 #define __INLINE_FAR_STD_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)                     \
156 	__INLINE_SEGSEG_ROWCOPY__(D,S,C,SIZE,TYPE,%%fs:,)
157 /* video -> memory copies */
158 #define __INLINE_STD_FAR_COLCOPY__(DST,DSKP,SRC,SSKP,C,DM,SM,INS,SIZE,TYPE)   \
159 	__INLINE_386_COLCOPY__(DST,DSKP,SRC,SSKP,C,INS,mov,SIZE,TYPE,,%%fs:)
160 #define __INLINE_STD_FAR_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)                     \
161 	__INLINE_SEGSEG_ROWCOPY__(D,S,C,SIZE,TYPE,,%%fs:)
162 /* video -> video copies */
163 #define __INLINE_FAR_FAR_COLCOPY__(DST,DSKP,SRC,SSKP,C,DM,SM,INS,SIZE,TYPE)   \
164 	__INLINE_386_COLCOPY__(DST,DSKP,SRC,SSKP,C,INS,mov,SIZE,TYPE,%%fs:,%%fs:)
165 #define __INLINE_FAR_FAR_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)                     \
166 	__INLINE_SEGSEG_ROWCOPY__(D,S,C,SIZE,TYPE,%%fs:,%%fs:)
167 #else   /* I386_GCC_FAR_MEMORY */
168 #define __INLINE_FAR_STD_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)                     \
169 	__INLINE_STD_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)
170 #define __INLINE_STD_FAR_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)                     \
171 	__INLINE_STD_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)
172 #define __INLINE_FAR_FAR_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)                     \
173 	__INLINE_STD_ROWCOPY__(D,S,C,DM,SM,SIZE,TYPE)
174 #endif  /* I386_GCC_FAR_MEMORY */
175 
176 #define fwdcopy_set(AP,D,S,C) do {                                           \
177   int _scr_;                                                                 \
178   if ((AP)==(D))                                                             \
179     __asm__ volatile("\n"                                                    \
180 	  "    cld                                  \n"                      \
181 	  "    cmpl    $4,%2                        \n"                      \
182 	  "    jb      3f                           \n"                      \
183 	  "    testl   $1,%0                        \n"                      \
184 	  "    je      1f                           \n"                      \
185 	  "    movsb                                \n"                      \
186 	  "    decl    %2                           \n"                      \
187 	  "1:  testl   $2,%0                        \n"                      \
188 	  "    je      2f                           \n"                      \
189 	  "    movsw                                \n"                      \
190 	  "    decl    %2                           \n"                      \
191 	  "    decl    %2                           \n"                      \
192 	  "2:  movl    %2,%3                        \n"                      \
193 	  "    shrl    $2,%3                        \n"                      \
194 	  "    je      3f                           \n"                      \
195 	  "    rep                                  \n"                      \
196 	  "    movsl                                \n"                      \
197 	  "3:  testl   $2,%2                        \n"                      \
198 	  "    je      4f                           \n"                      \
199 	  "    movsw                                \n"                      \
200 	  "4:  testl   $1,%2                        \n"                      \
201 	  "    je      5f                           \n"                      \
202 	  "    movsb                                \n"                      \
203 	  "5:                                         "                      \
204 	  : "=D" ((void *)(D)),"=S" ((void *)(S)),"=r" ((int)(C)),           \
205 	    "=&c" ((int)_scr_)                                               \
206 	  : "0"  ((void *)(D)), "1" ((void *)(S)), "2" ((int)(C))            \
207 	  : "memory"                                                         \
208     );                                                                       \
209   else                                                                       \
210     __asm__ volatile("\n"                                                    \
211 	  "    cld                                  \n"                      \
212 	  "    cmpl    $4,%2                        \n"                      \
213 	  "    jb      3f                           \n"                      \
214 	  "    testl   $1,%1                        \n"                      \
215 	  "    je      1f                           \n"                      \
216 	  "    movsb                                \n"                      \
217 	  "    decl    %2                           \n"                      \
218 	  "1:  testl   $2,%1                        \n"                      \
219 	  "    je      2f                           \n"                      \
220 	  "    movsw                                \n"                      \
221 	  "    decl    %2                           \n"                      \
222 	  "    decl    %2                           \n"                      \
223 	  "2:  movl    %2,%3                        \n"                      \
224 	  "    shrl    $2,%3                        \n"                      \
225 	  "    je      3f                           \n"                      \
226 	  "    rep                                  \n"                      \
227 	  "    movsl                                \n"                      \
228 	  "3:  testl   $2,%2                        \n"                      \
229 	  "    je      4f                           \n"                      \
230 	  "    movsw                                \n"                      \
231 	  "4:  testl   $1,%2                        \n"                      \
232 	  "    je      5f                           \n"                      \
233 	  "    movsb                                \n"                      \
234 	  "5:                                         "                      \
235 	  : "=D" ((void *)(D)),"=S" ((void *)(S)),"=r" ((int)(C)),           \
236 	    "=&c" ((int)_scr_)                                               \
237 	  : "0"  ((void *)(D)), "1" ((void *)(S)), "2" ((int)(C))            \
238 	  : "memory"                                                         \
239     );                                                                       \
240 } while (0)
241 
242 #endif /* __i386__ */
243 
244