URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [uclinux/] [uC-libc/] [include/] [asm/] [segment.h] - Rev 1778
Go to most recent revision | Compare with Previous | Blame | View Log
#ifndef _OR1K_SEGMENT_H #define _OR1K_SEGMENT_H /* define constants */ /* Address spaces (FC0-FC2) */ #define USER_DATA (1) #ifndef USER_DS #define USER_DS (USER_DATA) #endif #define USER_PROGRAM (2) #define SUPER_DATA (5) #ifndef KERNEL_DS #define KERNEL_DS (SUPER_DATA) #endif #define SUPER_PROGRAM (6) #define CPU_SPACE (7) #ifndef __ASSEMBLY__ /* * Uh, these should become the main single-value transfer routines.. * They automatically use the right size if we just have the right * pointer type.. */ #define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))) #define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))) /* * This is a silly but good way to make sure that * the __put_user function is indeed always optimized, * and that we use the correct sizes.. */ extern int bad_user_access_length(void); #define __ptr(x) ((unsigned long *)(x)) static inline void __put_user(unsigned long x, void * y, int size) { #if 0 switch (size) { case 1: __asm__ ("moveb %0,%1" : /* no outputs */ :"d" (x),"m" (*__ptr(y)) : "memory"); break; case 2: __asm__ ("movew %0,%1" : /* no outputs */ :"d" (x),"m" (*__ptr(y)) : "memory"); break; case 4: __asm__ ("movel %0,%1" : /* no outputs */ :"d" (x),"m" (*__ptr(y)) : "memory"); break; default: bad_user_access_length(); } #else switch (size) { case 1: *(char *) y = x; break; case 2: *(short *) y = x; break; case 4: *(int *) y = x; break; case 8: *(long *) y = x; break; default: bad_user_access_length(); } #endif } static inline unsigned long __get_user(const void * y, int size) { #if 0 unsigned long result; switch (size) { case 1: __asm__ ("moveb %1,%0" :"=d" (result) :"m" (*__ptr(y))); return (unsigned char) result; case 2: __asm__ ("movew %1,%0" :"=d" (result) :"m" (*__ptr(y))); return (unsigned short) result; case 4: __asm__ ("movel %1,%0" :"=d" (result) :"m" (*__ptr(y))); return result; default: return bad_user_access_length(); } #else switch (size) { case 1: return *(unsigned char *) y; case 2: return *(unsigned short *) y; case 4: return *(unsigned int *) y; case 8: return *(unsigned long *) y; default: return bad_user_access_length(); } #endif } #undef __ptr /* * These are deprecated.. * * Use "put_user()" and "get_user()" with the proper pointer types instead. */ #define get_fs_byte(addr) __get_user((const unsigned char *)(addr),1) #define get_fs_word(addr) __get_user((const unsigned short *)(addr),2) #define get_fs_long(addr) __get_user((const unsigned int *)(addr),4) #define put_fs_byte(x,addr) __put_user((x),(unsigned char *)(addr),1) #define put_fs_word(x,addr) __put_user((x),(unsigned short *)(addr),2) #define put_fs_long(x,addr) __put_user((x),(unsigned int *)(addr),4) #ifdef WE_REALLY_WANT_TO_USE_A_BROKEN_INTERFACE static inline unsigned char get_user_byte(const char * addr) { return __get_user(addr,1); } static inline unsigned short get_user_word(const short *addr) { return __get_user(addr,2); } static inline unsigned long get_user_long(const int *addr) { return __get_user(addr,4); } static inline void put_user_byte(char val,char *addr) { __put_user(val, addr, 1); } static inline void put_user_word(short val,short * addr) { __put_user(val, addr, 2); } static inline void put_user_long(unsigned long val,int * addr) { __put_user(val, addr, 4); } #endif static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n) { memcpy(to, from, n); /* Gah, idiots! */ #if 0 unsigned long tmp; if (n == 0) return; tmp = n; n >>= 2; if (n != 0) __asm__ __volatile__ ("1:\t" "movel %1@+,%/d0\n\t" "movel %/d0,%2@+\n\t" /* moves */ "dbra %0,1b\n\t" "clrw %0\n\t" "subql #1,%0\n\t" "bccs 1b\n\t" : "=d" (n), "=a" (from), "=a" (to) : "0" (n-1), "1" (from), "2" (to) : "d0", "memory"); if (tmp & 2) __asm__ __volatile__ ("movew %0@+,%/d0\n\t" "movew %/d0,%1@+\n\t" /* moves */ : "=a" (from), "=a" (to) : "0" (from), "1" (to) : "d0", "memory"); if (tmp & 1) __asm__ __volatile__ ("moveb %0@,%/d0\n\t" "moveb %/d0,%1@\n\t" /* moves */ : /* no outputs */ : "a" (from), "a" (to) : "d0", "memory"); #endif } static inline void __constant_memcpy_tofs(void * to, const void * from, unsigned long n) { memcpy(to, from, n); #if 0 switch (n) { case 0: return; case 1: __put_user(*(const char *) from, (char *) to, 1); return; case 2: __put_user(*(const short *) from, (short *) to, 2); return; case 3: __put_user(*(const short *) from, (short *) to, 2); __put_user(*(2+(const char *) from), 2+(char *) to, 1); return; case 4: __put_user(*(const int *) from, (int *) to, 4); return; case 8: __put_user(*(const int *) from, (int *) to, 4); __put_user(*(1+(const int *) from), 1+(int *) to, 4); return; case 12: __put_user(*(const int *) from, (int *) to, 4); __put_user(*(1+(const int *) from), 1+(int *) to, 4); __put_user(*(2+(const int *) from), 2+(int *) to, 4); return; case 16: __put_user(*(const int *) from, (int *) to, 4); __put_user(*(1+(const int *) from), 1+(int *) to, 4); __put_user(*(2+(const int *) from), 2+(int *) to, 4); __put_user(*(3+(const int *) from), 3+(int *) to, 4); return; } /* moves */ #define COMMON(x) \ __asm__ __volatile__ ("1:\n\t" \ "movel %1@+,%/d0\n\t" \ "movel %/d0,%2@+\n\t" \ "dbra %0,1b\n\t" \ "clrw %0\n\t" \ "subql #1,%0\n\t" \ "bccs 1b\n\t" \ x \ : "=d" (n), "=a" (from), "=a" (to) \ : "1" (from), "2" (to), "0" (n/4-1) \ : "d0", "memory"); switch (n % 4) { case 0: COMMON(""); return; case 1: COMMON("moveb %1@+,%/d0; moveb %/d0,%2@+"); /* moves */ return; case 2: COMMON("movew %1@+,%/d0; movew %/d0,%2@+"); /* moves */ return; case 3: COMMON("movew %1@+,%/d0; movew %/d0,%2@+\n\t" /* moves */ "moveb %1@+,%/d0; moveb %/d0,%2@+"); /* moves */ return; } #undef COMMON #endif } static inline void __generic_memcpy_fromfs(void * to, const void * from, unsigned long n) { memcpy(to, from, n); /* Gah, idiots! */ #if 0 unsigned long tmp; if (n == 0) return; tmp = n; n >>= 2; if (n != 0) __asm__ __volatile__ ("1:\t" "movel %1@+,%/d0\n\t" /* moves */ "movel %/d0,%2@+\n\t" "dbra %0,1b\n\t" "clrw %0\n\t" "subql #1,%0\n\t" "bccs 1b\n\t" : "=d" (n), "=a" (from), "=a" (to) : "0" (n-1), "1" (from), "2" (to) : "d0", "memory"); if (tmp & 2) __asm__ __volatile__ ("movew %0@+,%/d0\n\t" /* moves */ "movew %/d0,%1@+\n\t" : "=a" (from), "=a" (to) : "0" (from), "1" (to) : "d0", "memory"); if (tmp & 1) __asm__ __volatile__ ("moveb %0@,%/d0\n\t" /* moves */ "moveb %/d0,%1@\n\t" : /* no outputs */ : "a" (from), "a" (to) : "d0", "memory"); #endif } static inline void __constant_memcpy_fromfs(void * to, const void * from, unsigned long n) { memcpy(to, from, n); #if 0 switch (n) { case 0: return; case 1: *(char *)to = __get_user((const char *) from, 1); return; case 2: *(short *)to = __get_user((const short *) from, 2); return; case 3: *(short *) to = __get_user((const short *) from, 2); *((char *) to + 2) = __get_user(2+(const char *) from, 1); return; case 4: *(int *) to = __get_user((const int *) from, 4); return; case 8: *(int *) to = __get_user((const int *) from, 4); *(1+(int *) to) = __get_user(1+(const int *) from, 4); return; case 12: *(int *) to = __get_user((const int *) from, 4); *(1+(int *) to) = __get_user(1+(const int *) from, 4); *(2+(int *) to) = __get_user(2+(const int *) from, 4); return; case 16: *(int *) to = __get_user((const int *) from, 4); *(1+(int *) to) = __get_user(1+(const int *) from, 4); *(2+(int *) to) = __get_user(2+(const int *) from, 4); *(3+(int *) to) = __get_user(3+(const int *) from, 4); return; } /*moves*/ #define COMMON(x) \ __asm__ __volatile__ ("1:\n\t" \ "movel %1@+,%/d0\n\t" \ "movel %/d0,%2@+\n\t" \ "dbra %0,1b\n\t" \ "clrw %0\n\t" \ "subql #1,%0\n\t" \ "bccs 1b\n\t" \ x \ : "=d" (n), "=a" (from), "=a" (to) \ : "1" (from), "2" (to), "0" (n/4-1) \ : "d0", "memory"); switch (n % 4) { case 0: COMMON(""); return; case 1: COMMON("moveb %1@+,%/d0; moveb %/d0,%2@+"); /* moves */ return; case 2: COMMON("movew %1@+,%/d0; movew %/d0,%2@+"); /* moves */ return; case 3: COMMON("movew %1@+,%/d0; movew %/d0,%2@+\n\t" /* moves */ "moveb %1@+,%/d0; moveb %/d0,%2@+"); /* moves */ return; } #undef COMMON #endif } #if 0 #define memcpy_fromfs(to, from, n) \ (__builtin_constant_p(n) ? \ __constant_memcpy_fromfs((to),(from),(n)) : \ __generic_memcpy_fromfs((to),(from),(n))) #define memcpy_tofs(to, from, n) \ (__builtin_constant_p(n) ? \ __constant_memcpy_tofs((to),(from),(n)) : \ __generic_memcpy_tofs((to),(from),(n))) #else #define put_fs_quad(x,addr) put_user_quad((x),(long *)(addr)) #define memcpy_fromfs(to, from, n) memcpy((to),(from),(n)) #define memcpy_tofs(to, from, n) memcpy((to),(from),(n)) #endif /* * Get/set the SFC/DFC registers for MOVES instructions */ static inline unsigned long get_fs(void) { #ifdef NO_MM return USER_DS; #else unsigned long _v; __asm__ ("movec %/dfc,%0":"=r" (_v):); return _v; #endif } static inline unsigned long get_ds(void) { /* return the supervisor data space code */ return KERNEL_DS; } static inline void set_fs(unsigned long val) { #ifndef NO_MM __asm__ __volatile__ ("movec %0,%/sfc\n\t" "movec %0,%/dfc\n\t" : /* no outputs */ : "r" (val) : "memory"); #endif } #endif /* __ASSEMBLY__ */ #endif /* _OR1K_SEGMENT_H */
Go to most recent revision | Compare with Previous | Blame | View Log