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