home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-m32r / system.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  9.3 KB  |  344 lines

  1. #ifndef _ASM_M32R_SYSTEM_H
  2. #define _ASM_M32R_SYSTEM_H
  3.  
  4. /*
  5.  * This file is subject to the terms and conditions of the GNU General Public
  6.  * License.  See the file "COPYING" in the main directory of this archive
  7.  * for more details.
  8.  *
  9.  * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
  10.  * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  11.  */
  12.  
  13. #include <asm/assembler.h>
  14.  
  15. #ifdef __KERNEL__
  16.  
  17. /*
  18.  * switch_to(prev, next) should switch from task `prev' to `next'
  19.  * `prev' will never be the same as `next'.
  20.  *
  21.  * `next' and `prev' should be task_t, but it isn't always defined
  22.  */
  23.  
  24. #define switch_to(prev, next, last)  do { \
  25.     __asm__ __volatile__ ( \
  26.         "    seth    lr, #high(1f)                \n" \
  27.         "    or3    lr, lr, #low(1f)            \n" \
  28.         "    st    lr, @%4  ; store old LR            \n" \
  29.         "    ld    lr, @%5  ; load new LR            \n" \
  30.         "    st    sp, @%2  ; store old SP            \n" \
  31.         "    ld    sp, @%3  ; load new SP            \n" \
  32.         "    push    %1  ; store `prev' on new stack        \n" \
  33.         "    jmp    lr                    \n" \
  34.         "    .fillinsn                    \n" \
  35.         "1:                            \n" \
  36.         "    pop    %0  ; restore `__last' from new stack    \n" \
  37.         : "=r" (last) \
  38.         : "0" (prev), \
  39.           "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
  40.           "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
  41.         : "memory", "lr" \
  42.     ); \
  43. } while(0)
  44.  
  45. /*
  46.  * On SMP systems, when the scheduler does migration-cost autodetection,
  47.  * it needs a way to flush as much of the CPU's caches as possible.
  48.  *
  49.  * TODO: fill this in!
  50.  */
  51. static inline void sched_cacheflush(void)
  52. {
  53. }
  54.  
  55. /* Interrupt Control */
  56. #if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
  57. #define local_irq_enable() \
  58.     __asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
  59. #define local_irq_disable() \
  60.     __asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
  61. #else    /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
  62. static inline void local_irq_enable(void)
  63. {
  64.     unsigned long tmpreg;
  65.     __asm__ __volatile__(
  66.         "mvfc    %0, psw;        \n\t"
  67.         "or3    %0, %0, #0x0040;    \n\t"
  68.         "mvtc    %0, psw;        \n\t"
  69.     : "=&r" (tmpreg) : : "cbit", "memory");
  70. }
  71.  
  72. static inline void local_irq_disable(void)
  73. {
  74.     unsigned long tmpreg0, tmpreg1;
  75.     __asm__ __volatile__(
  76.         "ld24    %0, #0    ; Use 32-bit insn. \n\t"
  77.         "mvfc    %1, psw    ; No interrupt can be accepted here. \n\t"
  78.         "mvtc    %0, psw    \n\t"
  79.         "and3    %0, %1, #0xffbf    \n\t"
  80.         "mvtc    %0, psw    \n\t"
  81.     : "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
  82. }
  83. #endif    /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
  84.  
  85. #define local_save_flags(x) \
  86.     __asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */)
  87.  
  88. #define local_irq_restore(x) \
  89.     __asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \
  90.         : "r" (x) : "cbit", "memory")
  91.  
  92. #if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
  93. #define local_irq_save(x)                \
  94.     __asm__ __volatile__(                \
  95.           "mvfc    %0, psw;        \n\t"    \
  96.           "clrpsw    #0x40 -> nop;        \n\t"    \
  97.           : "=r" (x) : /* no input */ : "memory")
  98. #else    /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
  99. #define local_irq_save(x)                 \
  100.     ({                        \
  101.         unsigned long tmpreg;            \
  102.         __asm__ __volatile__(             \
  103.             "ld24    %1, #0 \n\t"         \
  104.             "mvfc    %0, psw \n\t"        \
  105.             "mvtc    %1, psw \n\t"        \
  106.             "and3    %1, %0, #0xffbf \n\t"    \
  107.             "mvtc    %1, psw \n\t"         \
  108.             : "=r" (x), "=&r" (tmpreg)    \
  109.             : : "cbit", "memory");        \
  110.     })
  111. #endif    /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
  112.  
  113. #define irqs_disabled()                    \
  114.     ({                        \
  115.         unsigned long flags;            \
  116.         local_save_flags(flags);        \
  117.         !(flags & 0x40);            \
  118.     })
  119.  
  120. #define nop()    __asm__ __volatile__ ("nop" : : )
  121.  
  122. #define xchg(ptr,x) \
  123.     ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
  124.  
  125. #define tas(ptr)    (xchg((ptr),1))
  126.  
  127. #ifdef CONFIG_SMP
  128. extern void  __xchg_called_with_bad_pointer(void);
  129. #endif
  130.  
  131. #ifdef CONFIG_CHIP_M32700_TS1
  132. #define DCACHE_CLEAR(reg0, reg1, addr)                \
  133.     "seth    "reg1", #high(dcache_dummy);        \n\t"    \
  134.     "or3    "reg1", "reg1", #low(dcache_dummy);    \n\t"    \
  135.     "lock    "reg0", @"reg1";            \n\t"    \
  136.     "add3    "reg0", "addr", #0x1000;        \n\t"    \
  137.     "ld    "reg0", @"reg0";            \n\t"    \
  138.     "add3    "reg0", "addr", #0x2000;        \n\t"    \
  139.     "ld    "reg0", @"reg0";            \n\t"    \
  140.     "unlock    "reg0", @"reg1";            \n\t"
  141.     /* FIXME: This workaround code cannot handle kenrel modules
  142.      * correctly under SMP environment.
  143.      */
  144. #else    /* CONFIG_CHIP_M32700_TS1 */
  145. #define DCACHE_CLEAR(reg0, reg1, addr)
  146. #endif    /* CONFIG_CHIP_M32700_TS1 */
  147.  
  148. static inline unsigned long
  149. __xchg(unsigned long x, volatile void * ptr, int size)
  150. {
  151.     unsigned long flags;
  152.     unsigned long tmp = 0;
  153.  
  154.     local_irq_save(flags);
  155.  
  156.     switch (size) {
  157. #ifndef CONFIG_SMP
  158.     case 1:
  159.         __asm__ __volatile__ (
  160.             "ldb    %0, @%2 \n\t"
  161.             "stb    %1, @%2 \n\t"
  162.             : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
  163.         break;
  164.     case 2:
  165.         __asm__ __volatile__ (
  166.             "ldh    %0, @%2 \n\t"
  167.             "sth    %1, @%2 \n\t"
  168.             : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
  169.         break;
  170.     case 4:
  171.         __asm__ __volatile__ (
  172.             "ld    %0, @%2 \n\t"
  173.             "st    %1, @%2 \n\t"
  174.             : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
  175.         break;
  176. #else  /* CONFIG_SMP */
  177.     case 4:
  178.         __asm__ __volatile__ (
  179.             DCACHE_CLEAR("%0", "r4", "%2")
  180.             "lock    %0, @%2;    \n\t"
  181.             "unlock    %1, @%2;    \n\t"
  182.             : "=&r" (tmp) : "r" (x), "r" (ptr)
  183.             : "memory"
  184. #ifdef CONFIG_CHIP_M32700_TS1
  185.             , "r4"
  186. #endif    /* CONFIG_CHIP_M32700_TS1 */
  187.         );
  188.         break;
  189.     default:
  190.         __xchg_called_with_bad_pointer();
  191. #endif  /* CONFIG_SMP */
  192.     }
  193.  
  194.     local_irq_restore(flags);
  195.  
  196.     return (tmp);
  197. }
  198.  
  199. #define __HAVE_ARCH_CMPXCHG    1
  200.  
  201. static inline unsigned long
  202. __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
  203. {
  204.     unsigned long flags;
  205.     unsigned int retval;
  206.  
  207.     local_irq_save(flags);
  208.     __asm__ __volatile__ (
  209.             DCACHE_CLEAR("%0", "r4", "%1")
  210.             M32R_LOCK" %0, @%1;    \n"
  211.         "    bne    %0, %2, 1f;    \n"
  212.             M32R_UNLOCK" %3, @%1;    \n"
  213.         "    bra    2f;        \n"
  214.                 "       .fillinsn        \n"
  215.         "1:"
  216.             M32R_UNLOCK" %0, @%1;    \n"
  217.                 "       .fillinsn        \n"
  218.         "2:"
  219.             : "=&r" (retval)
  220.             : "r" (p), "r" (old), "r" (new)
  221.             : "cbit", "memory"
  222. #ifdef CONFIG_CHIP_M32700_TS1
  223.             , "r4"
  224. #endif  /* CONFIG_CHIP_M32700_TS1 */
  225.         );
  226.     local_irq_restore(flags);
  227.  
  228.     return retval;
  229. }
  230.  
  231. /* This function doesn't exist, so you'll get a linker error
  232.    if something tries to do an invalid cmpxchg().  */
  233. extern void __cmpxchg_called_with_bad_pointer(void);
  234.  
  235. static inline unsigned long
  236. __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
  237. {
  238.     switch (size) {
  239.     case 4:
  240.         return __cmpxchg_u32(ptr, old, new);
  241. #if 0    /* we don't have __cmpxchg_u64 */
  242.     case 8:
  243.         return __cmpxchg_u64(ptr, old, new);
  244. #endif /* 0 */
  245.     }
  246.     __cmpxchg_called_with_bad_pointer();
  247.     return old;
  248. }
  249.  
  250. #define cmpxchg(ptr,o,n)                         \
  251.   ({                                     \
  252.      __typeof__(*(ptr)) _o_ = (o);                     \
  253.      __typeof__(*(ptr)) _n_ = (n);                     \
  254.      (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,         \
  255.                     (unsigned long)_n_, sizeof(*(ptr))); \
  256.   })
  257.  
  258. #endif  /* __KERNEL__ */
  259.  
  260. /*
  261.  * Memory barrier.
  262.  *
  263.  * mb() prevents loads and stores being reordered across this point.
  264.  * rmb() prevents loads being reordered across this point.
  265.  * wmb() prevents stores being reordered across this point.
  266.  */
  267. #define mb()   barrier()
  268. #define rmb()  mb()
  269. #define wmb()  mb()
  270.  
  271. /**
  272.  * read_barrier_depends - Flush all pending reads that subsequents reads
  273.  * depend on.
  274.  *
  275.  * No data-dependent reads from memory-like regions are ever reordered
  276.  * over this barrier.  All reads preceding this primitive are guaranteed
  277.  * to access memory (but not necessarily other CPUs' caches) before any
  278.  * reads following this primitive that depend on the data return by
  279.  * any of the preceding reads.  This primitive is much lighter weight than
  280.  * rmb() on most CPUs, and is never heavier weight than is
  281.  * rmb().
  282.  *
  283.  * These ordering constraints are respected by both the local CPU
  284.  * and the compiler.
  285.  *
  286.  * Ordering is not guaranteed by anything other than these primitives,
  287.  * not even by data dependencies.  See the documentation for
  288.  * memory_barrier() for examples and URLs to more information.
  289.  *
  290.  * For example, the following code would force ordering (the initial
  291.  * value of "a" is zero, "b" is one, and "p" is "&a"):
  292.  *
  293.  * <programlisting>
  294.  *      CPU 0                           CPU 1
  295.  *
  296.  *      b = 2;
  297.  *      memory_barrier();
  298.  *      p = &b;                         q = p;
  299.  *                                      read_barrier_depends();
  300.  *                                      d = *q;
  301.  * </programlisting>
  302.  *
  303.  *
  304.  * because the read of "*q" depends on the read of "p" and these
  305.  * two reads are separated by a read_barrier_depends().  However,
  306.  * the following code, with the same initial values for "a" and "b":
  307.  *
  308.  * <programlisting>
  309.  *      CPU 0                           CPU 1
  310.  *
  311.  *      a = 2;
  312.  *      memory_barrier();
  313.  *      b = 3;                          y = b;
  314.  *                                      read_barrier_depends();
  315.  *                                      x = a;
  316.  * </programlisting>
  317.  *
  318.  * does not enforce ordering, since there is no data dependency between
  319.  * the read of "a" and the read of "b".  Therefore, on some CPUs, such
  320.  * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
  321.  * in cases like thiswhere there are no data dependencies.
  322.  **/
  323.  
  324. #define read_barrier_depends()    do { } while (0)
  325.  
  326. #ifdef CONFIG_SMP
  327. #define smp_mb()    mb()
  328. #define smp_rmb()    rmb()
  329. #define smp_wmb()    wmb()
  330. #define smp_read_barrier_depends()    read_barrier_depends()
  331. #else
  332. #define smp_mb()    barrier()
  333. #define smp_rmb()    barrier()
  334. #define smp_wmb()    barrier()
  335. #define smp_read_barrier_depends()    do { } while (0)
  336. #endif
  337.  
  338. #define set_mb(var, value) do { xchg(&var, value); } while (0)
  339. #define set_wmb(var, value) do { var = value; wmb(); } while (0)
  340.  
  341. #define arch_align_stack(x) (x)
  342.  
  343. #endif  /* _ASM_M32R_SYSTEM_H */
  344.