Do core interrupt masking in a less general fashion and save some instructions to...
[kugel-rb.git] / firmware / target / arm / system-arm.h
blob3f1dfb16c8324cdf503087007c4a06bae5aed3f0
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Alan Korr
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #ifndef SYSTEM_ARM_H
20 #define SYSTEM_ARM_H
22 #define nop \
23 asm volatile ("nop")
26 /* This gets too complicated otherwise with all the ARM variation and would
27 have conflicts with another system-target.h elsewhere so include a
28 subheader from here. */
30 static inline uint16_t swap16(uint16_t value)
32 result[15..8] = value[ 7..0];
33 result[ 7..0] = value[15..8];
36 return (value >> 8) | (value << 8);
39 static inline uint32_t swap32(uint32_t value)
41 result[31..24] = value[ 7.. 0];
42 result[23..16] = value[15.. 8];
43 result[15.. 8] = value[23..16];
44 result[ 7.. 0] = value[31..24];
47 uint32_t tmp;
49 asm volatile (
50 "eor %1, %0, %0, ror #16 \n\t"
51 "bic %1, %1, #0xff0000 \n\t"
52 "mov %0, %0, ror #8 \n\t"
53 "eor %0, %0, %1, lsr #8 \n\t"
54 : "+r" (value), "=r" (tmp)
56 return value;
59 static inline uint32_t swap_odd_even32(uint32_t value)
62 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
63 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
65 uint32_t tmp;
67 asm volatile ( /* ABCD */
68 "bic %1, %0, #0x00ff00 \n\t" /* AB.D */
69 "bic %0, %0, #0xff0000 \n\t" /* A.CD */
70 "mov %0, %0, lsr #8 \n\t" /* .A.C */
71 "orr %0, %0, %1, lsl #8 \n\t" /* B.D.|.A.C */
72 : "+r" (value), "=r" (tmp) /* BADC */
74 return value;
77 /* Core-level interrupt masking */
79 /* This one returns the old status */
80 #define IRQ_ENABLED 0x00
81 #define IRQ_DISABLED 0x80
82 #define IRQ_STATUS 0x80
83 #define FIQ_ENABLED 0x00
84 #define FIQ_DISABLED 0x40
85 #define FIQ_STATUS 0x40
86 #define IRQ_FIQ_ENABLED 0x00
87 #define IRQ_FIQ_DISABLED 0xc0
88 #define IRQ_FIQ_STATUS 0xc0
89 #define HIGHEST_IRQ_LEVEL IRQ_DISABLED
91 #define set_irq_level(status) \
92 set_interrupt_status((status), IRQ_STATUS)
93 #define set_fiq_status(status) \
94 set_interrupt_status((status), FIQ_STATUS)
96 static inline int set_interrupt_status(int status, int mask)
98 unsigned long cpsr;
99 int oldstatus;
100 /* Read the old levels and set the new ones */
101 asm volatile (
102 "mrs %1, cpsr \n"
103 "bic %0, %1, %[mask] \n"
104 "orr %0, %0, %2 \n"
105 "msr cpsr_c, %0 \n"
106 : "=&r,r"(cpsr), "=&r,r"(oldstatus)
107 : "r,i"(status & mask), [mask]"i,i"(mask));
109 return oldstatus;
112 static inline void enable_interrupt(int mask)
114 /* Clear I and/or F disable bit */
115 int tmp;
116 asm volatile (
117 "mrs %0, cpsr \n"
118 "bic %0, %0, %1 \n"
119 "msr cpsr_c, %0 \n"
120 : "=&r"(tmp) : "i"(mask));
123 static inline void disable_interrupt(int mask)
125 /* Set I and/or F disable bit */
126 int tmp;
127 asm volatile (
128 "mrs %0, cpsr \n"
129 "orr %0, %0, %1 \n"
130 "msr cpsr_c, %0 \n"
131 : "=&r"(tmp) : "i"(mask));
134 #define disable_irq(void) \
135 disable_interrupt(IRQ_STATUS)
137 #define enable_irq(void) \
138 enable_interrupt(IRQ_STATUS)
140 #define disable_fiq(void) \
141 disable_interrupt(FIQ_STATUS)
143 #define enable_fiq(void) \
144 enable_interrupt(FIQ_STATUS)
146 static inline int disable_interrupt_save(int mask)
148 /* Set I and/or F disable bit and return old cpsr value */
149 int cpsr, tmp;
150 asm volatile (
151 "mrs %1, cpsr \n"
152 "orr %0, %1, %2 \n"
153 "msr cpsr_c, %0 \n"
154 : "=&r"(tmp), "=&r"(cpsr)
155 : "i"(mask));
156 return cpsr;
159 #define disable_irq_save() \
160 disable_interrupt_save(IRQ_STATUS)
162 #define disable_fiq_save() \
163 disable_interrupt_save(FIQ_STATUS)
165 static inline void restore_interrupt(int cpsr)
167 /* Set cpsr_c from value returned by disable_interrupt_save
168 * or set_interrupt_status */
169 asm volatile ("msr cpsr_c, %0" : : "r"(cpsr));
172 #define restore_irq(cpsr) \
173 restore_interrupt(cpsr)
175 #define restore_fiq(cpsr) \
176 restore_interrupt(cpsr)
178 #endif /* SYSTEM_ARM_H */