diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/arm/system-arm.h | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/firmware/target/arm/system-arm.h b/firmware/target/arm/system-arm.h index 2d8c6f2c9f..e5d3f35001 100644 --- a/firmware/target/arm/system-arm.h +++ b/firmware/target/arm/system-arm.h | |||
@@ -110,6 +110,18 @@ static inline int set_interrupt_status(int status, int mask) | |||
110 | unsigned long cpsr; | 110 | unsigned long cpsr; |
111 | int oldstatus; | 111 | int oldstatus; |
112 | /* Read the old levels and set the new ones */ | 112 | /* Read the old levels and set the new ones */ |
113 | #if defined(CREATIVE_ZVM) && defined(BOOTLOADER) | ||
114 | // FIXME: This workaround is for a problem with inlining; | ||
115 | // for some reason 'mask' gets treated as a variable/non-immediate constant | ||
116 | // but only on this build. All others (including the nearly-identical mrobe500boot) are fine | ||
117 | asm volatile ( | ||
118 | "mrs %1, cpsr \n" | ||
119 | "bic %0, %1, %[mask] \n" | ||
120 | "orr %0, %0, %2 \n" | ||
121 | "msr cpsr_c, %0 \n" | ||
122 | : "=&r,r"(cpsr), "=&r,r"(oldstatus) | ||
123 | : "r,i"(status & mask), [mask]"r,i"(mask)); | ||
124 | #else | ||
113 | asm volatile ( | 125 | asm volatile ( |
114 | "mrs %1, cpsr \n" | 126 | "mrs %1, cpsr \n" |
115 | "bic %0, %1, %[mask] \n" | 127 | "bic %0, %1, %[mask] \n" |
@@ -117,7 +129,7 @@ static inline int set_interrupt_status(int status, int mask) | |||
117 | "msr cpsr_c, %0 \n" | 129 | "msr cpsr_c, %0 \n" |
118 | : "=&r,r"(cpsr), "=&r,r"(oldstatus) | 130 | : "=&r,r"(cpsr), "=&r,r"(oldstatus) |
119 | : "r,i"(status & mask), [mask]"i,i"(mask)); | 131 | : "r,i"(status & mask), [mask]"i,i"(mask)); |
120 | 132 | #endif | |
121 | return oldstatus; | 133 | return oldstatus; |
122 | } | 134 | } |
123 | 135 | ||