Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

asm.h

Go to the documentation of this file.
00001 // See the end of this file for license information.
00002 
00003 #ifndef TORSION_ASM_H
00004 #define TORSION_ASM_H
00005 
00006 // thank you, Linux kernel!
00007 // all the functions/macros that we don't use currently are #if 0'd out
00008 
00009 #define size_t unsigned int
00010 #define NULL 0
00011 
00012 // send a byte out to a port
00013 inline void
00014 outb(unsigned short int value, unsigned int port) {
00015   asm volatile("outb %%al, %%dx" : : "a" (value), "d" (port));
00016 }
00017 
00018 inline unsigned char
00019 inb(unsigned int port) {
00020    unsigned char value;
00021    asm volatile("inb %%dx, %%al" : "=a" (value) : "d" (port));
00022    return value;
00023 }
00024 
00025 #if 0
00026 static inline char * strcpy(char * dest,const char *src)
00027 {
00028 int d0, d1, d2;
00029 __asm__ __volatile__(
00030         "1:\tlodsb\n\t"
00031         "stosb\n\t"
00032         "testb %%al,%%al\n\t"
00033         "jne 1b"
00034         : "=&S" (d0), "=&D" (d1), "=&a" (d2)
00035         :"0" (src),"1" (dest) : "memory");
00036 return dest;
00037 }
00038 
00039 static inline char * strncpy(char * dest,const char *src,size_t count)
00040 {
00041 int d0, d1, d2, d3;
00042 __asm__ __volatile__(
00043         "1:\tdecl %2\n\t"
00044         "js 2f\n\t"
00045         "lodsb\n\t"
00046         "stosb\n\t"
00047         "testb %%al,%%al\n\t"
00048         "jne 1b\n\t"
00049         "rep\n\t"
00050         "stosb\n"
00051         "2:"
00052         : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
00053         :"0" (src),"1" (dest),"2" (count) : "memory");
00054 return dest;
00055 }
00056 
00057 static inline char * strcat(char * dest,const char * src)
00058 {
00059 int d0, d1, d2, d3;
00060 __asm__ __volatile__(
00061         "repne\n\t"
00062         "scasb\n\t"
00063         "decl %1\n"
00064         "1:\tlodsb\n\t"
00065         "stosb\n\t"
00066         "testb %%al,%%al\n\t"
00067         "jne 1b"
00068         : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
00069         : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
00070 return dest;
00071 }
00072 
00073 static inline char * strncat(char * dest,const char * src,size_t count)
00074 {
00075 int d0, d1, d2, d3;
00076 __asm__ __volatile__(
00077         "repne\n\t"
00078         "scasb\n\t"
00079         "decl %1\n\t"
00080         "movl %8,%3\n"
00081         "1:\tdecl %3\n\t"
00082         "js 2f\n\t"
00083         "lodsb\n\t"
00084         "stosb\n\t"
00085         "testb %%al,%%al\n\t"
00086         "jne 1b\n"
00087         "2:\txorl %2,%2\n\t"
00088         "stosb"
00089         : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
00090         : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
00091         : "memory");
00092 return dest;
00093 }
00094 
00095 static inline int strcmp(const char * cs,const char * ct)
00096 {
00097 int d0, d1;
00098 register int __res;
00099 __asm__ __volatile__(
00100         "1:\tlodsb\n\t"
00101         "scasb\n\t"
00102         "jne 2f\n\t"
00103         "testb %%al,%%al\n\t"
00104         "jne 1b\n\t"
00105         "xorl %%eax,%%eax\n\t"
00106         "jmp 3f\n"
00107         "2:\tsbbl %%eax,%%eax\n\t"
00108         "orb $1,%%al\n"
00109         "3:"
00110         :"=a" (__res), "=&S" (d0), "=&D" (d1)
00111                      :"1" (cs),"2" (ct));
00112 return __res;
00113 }
00114 
00115 static inline int strncmp(const char * cs,const char * ct,size_t count)
00116 {
00117 register int __res;
00118 int d0, d1, d2;
00119 __asm__ __volatile__(
00120         "1:\tdecl %3\n\t"
00121         "js 2f\n\t"
00122         "lodsb\n\t"
00123         "scasb\n\t"
00124         "jne 3f\n\t"
00125         "testb %%al,%%al\n\t"
00126         "jne 1b\n"
00127         "2:\txorl %%eax,%%eax\n\t"
00128         "jmp 4f\n"
00129         "3:\tsbbl %%eax,%%eax\n\t"
00130         "orb $1,%%al\n"
00131         "4:"
00132                      :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
00133                      :"1" (cs),"2" (ct),"3" (count));
00134 return __res;
00135 }
00136 
00137 static inline char * strchr(const char * s, int c)
00138 {
00139 int d0;
00140 register char * __res;
00141 __asm__ __volatile__(
00142         "movb %%al,%%ah\n"
00143         "1:\tlodsb\n\t"
00144         "cmpb %%ah,%%al\n\t"
00145         "je 2f\n\t"
00146         "testb %%al,%%al\n\t"
00147         "jne 1b\n\t"
00148         "movl $1,%1\n"
00149         "2:\tmovl %1,%0\n\t"
00150         "decl %0"
00151         :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
00152 return __res;
00153 }
00154 
00155 static inline char * strrchr(const char * s, int c)
00156 {
00157 int d0, d1;
00158 register char * __res;
00159 __asm__ __volatile__(
00160         "movb %%al,%%ah\n"
00161         "1:\tlodsb\n\t"
00162         "cmpb %%ah,%%al\n\t"
00163         "jne 2f\n\t"
00164         "leal -1(%%esi),%0\n"
00165         "2:\ttestb %%al,%%al\n\t"
00166         "jne 1b"
00167         :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
00168 return __res;
00169 }
00170 
00171 static inline size_t strlen(const char * s)
00172 {
00173 int d0;
00174 register int __res;
00175 __asm__ __volatile__(
00176         "repne\n\t"
00177         "scasb\n\t"
00178         "notl %0\n\t"
00179         "decl %0"
00180         :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
00181 return __res;
00182 }
00183 #endif
00184 
00185 static inline void * __memcpy(void * to, const void * from, size_t n)
00186 {
00187 int d0, d1, d2;
00188 __asm__ __volatile__(
00189         "rep ; movsl\n\t"
00190         "testb $2,%b4\n\t"
00191         "je 1f\n\t"
00192         "movsw\n"
00193         "1:\ttestb $1,%b4\n\t"
00194         "je 2f\n\t"
00195         "movsb\n"
00196         "2:"
00197         : "=&c" (d0), "=&D" (d1), "=&S" (d2)
00198         :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
00199         : "memory");
00200 return (to);
00201 }
00202 
00203 /*
00204  * This looks horribly ugly, but the compiler can optimize it totally,
00205  * as the count is constant.
00206  */
00207 static inline void * __constant_memcpy(void * to, const void * from, size_t n)
00208 {
00209         switch (n) {
00210                 case 0:
00211                         return to;
00212                 case 1:
00213                         *(unsigned char *)to = *(const unsigned char *)from;
00214                         return to;
00215                 case 2:
00216                         *(unsigned short *)to = *(const unsigned short *)from;
00217                         return to;
00218                 case 3:
00219                         *(unsigned short *)to = *(const unsigned short *)from;
00220                         *(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
00221                         return to;
00222                 case 4:
00223                         *(unsigned long *)to = *(const unsigned long *)from;
00224                         return to;
00225                 case 6: /* for Ethernet addresses */
00226                         *(unsigned long *)to = *(const unsigned long *)from;
00227                         *(2+(unsigned short *)to) = *(2+(const unsigned short *)from);
00228                         return to;
00229                 case 8:
00230                         *(unsigned long *)to = *(const unsigned long *)from;
00231                         *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
00232                         return to;
00233                 case 12:
00234                         *(unsigned long *)to = *(const unsigned long *)from;
00235                         *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
00236                         *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
00237                         return to;
00238                 case 16:
00239                         *(unsigned long *)to = *(const unsigned long *)from;
00240                         *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
00241                         *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
00242                         *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
00243                         return to;
00244                 case 20:
00245                         *(unsigned long *)to = *(const unsigned long *)from;
00246                         *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
00247                         *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
00248                         *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
00249                         *(4+(unsigned long *)to) = *(4+(const unsigned long *)from);
00250                         return to;
00251         }
00252 #define COMMON(x) \
00253 __asm__ __volatile__( \
00254         "rep ; movsl" \
00255         x \
00256         : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
00257         : "0" (n/4),"1" ((long) to),"2" ((long) from) \
00258         : "memory");
00259 {
00260         int d0, d1, d2;
00261         switch (n % 4) {
00262                 case 0: COMMON(""); return to;
00263                 case 1: COMMON("\n\tmovsb"); return to;
00264                 case 2: COMMON("\n\tmovsw"); return to;
00265                 default: COMMON("\n\tmovsw\n\tmovsb"); return to;
00266         }
00267 }
00268   
00269 #undef COMMON
00270 }
00271 
00272 #define memcpy(t, f, n) \
00273 (__builtin_constant_p(n) ? \
00274  __constant_memcpy((t),(f),(n)) : \
00275  __memcpy((t),(f),(n)))
00276 
00277 #if 0
00278 /*
00279  * struct_cpy(x,y), copy structure *x into (matching structure) *y.
00280  *
00281  * We get link-time errors if the structure sizes do not match.
00282  * There is no runtime overhead, it's all optimized away at
00283  * compile time.
00284  */
00285 extern void __struct_cpy_bug (void);
00286 
00287 #define struct_cpy(x,y)                         \
00288 ({                                              \
00289         if (sizeof(*(x)) != sizeof(*(y)))       \
00290                 __struct_cpy_bug;               \
00291         memcpy(x, y, sizeof(*(x)));             \
00292 })
00293 #endif
00294 
00295 static inline void * memmove(void * dest,const void * src, size_t n)
00296 {
00297 int d0, d1, d2;
00298 if (dest<src)
00299 __asm__ __volatile__(
00300         "rep\n\t"
00301         "movsb"
00302         : "=&c" (d0), "=&S" (d1), "=&D" (d2)
00303         :"0" (n),"1" (src),"2" (dest)
00304         : "memory");
00305 else
00306 __asm__ __volatile__(
00307         "std\n\t"
00308         "rep\n\t"
00309         "movsb\n\t"
00310         "cld"
00311         : "=&c" (d0), "=&S" (d1), "=&D" (d2)
00312         :"0" (n),
00313          "1" (n-1+(const char *)src),
00314          "2" (n-1+(char *)dest)
00315         :"memory");
00316 return dest;
00317 }
00318 
00319 #if 0
00320 #define memcmp __builtin_memcmp
00321 
00322 static inline void * memchr(const void * cs,int c,size_t count)
00323 {
00324 int d0;
00325 register void * __res;
00326 if (!count)
00327         return NULL;
00328 __asm__ __volatile__(
00329         "repne\n\t"
00330         "scasb\n\t"
00331         "je 1f\n\t"
00332         "movl $1,%0\n"
00333         "1:\tdecl %0"
00334         :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
00335 return __res;
00336 }
00337 #endif
00338 
00339 static inline void * __memset_generic(void * s, char c,size_t count)
00340 {
00341 int d0, d1;
00342 __asm__ __volatile__(
00343         "rep\n\t"
00344         "stosb"
00345         : "=&c" (d0), "=&D" (d1)
00346         :"a" (c),"1" (s),"0" (count)
00347         :"memory");
00348 return s;
00349 }
00350 
00351 /* we might want to write optimized versions of these later */
00352 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
00353 
00354 /*
00355  * memset(x,0,y) is a reasonably common thing to do, so we want to fill
00356  * things 32 bits at a time even when we don't know the size of the
00357  * area at compile-time..
00358  */
00359 static inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
00360 {
00361 int d0, d1;
00362 __asm__ __volatile__(
00363         "rep ; stosl\n\t"
00364         "testb $2,%b3\n\t"
00365         "je 1f\n\t"
00366         "stosw\n"
00367         "1:\ttestb $1,%b3\n\t"
00368         "je 2f\n\t"
00369         "stosb\n"
00370         "2:"
00371         : "=&c" (d0), "=&D" (d1)
00372         :"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
00373         :"memory");
00374 return (s);     
00375 }
00376 
00377 #if 0
00378 /* Added by Gertjan van Wingerde to make minix and sysv module work */
00379 static inline size_t strnlen(const char * s, size_t count)
00380 {
00381 int d0;
00382 register int __res;
00383 __asm__ __volatile__(
00384         "movl %2,%0\n\t"
00385         "jmp 2f\n"
00386         "1:\tcmpb $0,(%0)\n\t"
00387         "je 3f\n\t"
00388         "incl %0\n"
00389         "2:\tdecl %1\n\t"
00390         "cmpl $-1,%1\n\t"
00391         "jne 1b\n"
00392         "3:\tsubl %2,%0"
00393         :"=a" (__res), "=&d" (d0)
00394         :"c" (s),"1" (count));
00395 return __res;
00396 }
00397 /* end of additional stuff */
00398 
00399 extern char *strstr(const char *cs, const char *ct);
00400 #endif
00401 
00402 /*
00403  * This looks horribly ugly, but the compiler can optimize it totally,
00404  * as we by now know that both pattern and count is constant..
00405  */
00406 static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
00407 {
00408         switch (count) {
00409                 case 0:
00410                         return s;
00411                 case 1:
00412                         *(unsigned char *)s = pattern;
00413                         return s;
00414                 case 2:
00415                         *(unsigned short *)s = pattern;
00416                         return s;
00417                 case 3:
00418                         *(unsigned short *)s = pattern;
00419                         *(2+(unsigned char *)s) = pattern;
00420                         return s;
00421                 case 4:
00422                         *(unsigned long *)s = pattern;
00423                         return s;
00424         }
00425 #define COMMON(x) \
00426 __asm__  __volatile__( \
00427         "rep ; stosl" \
00428         x \
00429         : "=&c" (d0), "=&D" (d1) \
00430         : "a" (pattern),"0" (count/4),"1" ((long) s) \
00431         : "memory")
00432 {
00433         int d0, d1;
00434         switch (count % 4) {
00435                 case 0: COMMON(""); return s;
00436                 case 1: COMMON("\n\tstosb"); return s;
00437                 case 2: COMMON("\n\tstosw"); return s;
00438                 default: COMMON("\n\tstosw\n\tstosb"); return s;
00439         }
00440 }
00441   
00442 #undef COMMON
00443 }
00444 
00445 #define __constant_c_x_memset(s, c, count) \
00446 (__builtin_constant_p(count) ? \
00447  __constant_c_and_count_memset((s),(c),(count)) : \
00448  __constant_c_memset((s),(c),(count)))
00449 
00450 #define __memset(s, c, count) \
00451 (__builtin_constant_p(count) ? \
00452  __constant_count_memset((s),(c),(count)) : \
00453  __memset_generic((s),(c),(count)))
00454 
00455 #define __HAVE_ARCH_MEMSET
00456 #define memset(s, c, count) \
00457 (__builtin_constant_p(c) ? \
00458  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \
00459  __memset((s),(c),(count)))
00460 
00461 #if 0
00462 /*
00463  * find the first occurrence of byte 'c', or 1 past the area if none
00464  */
00465 #define __HAVE_ARCH_MEMSCAN
00466 static inline void * memscan(void * addr, int c, size_t size)
00467 {
00468         if (!size)
00469                 return addr;
00470         __asm__("repnz; scasb\n\t"
00471                 "jnz 1f\n\t"
00472                 "dec %%edi\n"
00473                 "1:"
00474                 : "=D" (addr), "=c" (size)
00475                 : "0" (addr), "1" (size), "a" (c));
00476         return addr;
00477 }
00478 #endif
00479 
00480 #endif
00481 
00482 /* Torsion Operating System, Copyright (C) 2000-2002 Dan Helfman
00483  *
00484  * This program is free software; you can redistribute it and/or modify it
00485  * under the terms of the GNU General Public License as published by the
00486  * Free Software Foundation; either version 2 of the License, or (at your
00487  * option) any later version.
00488  * 
00489  * This program is distributed in the hope that it will be useful, but
00490  * WITHOUT ANY WARRANTY; without even the implied warranty of
00491  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00492  * General Public License for more details (in the COPYING file).
00493  * 
00494  * You should have received a copy of the GNU General Public License along
00495  * with this program; if not, write to the Free Software Foundation, Inc.,
00496  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00497  */

Torsion Operating System, Copyright (C) 2000-2002 Dan Helfman