summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/system-arm.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/system-arm.h')
-rw-r--r--firmware/target/arm/system-arm.h14
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)
unsigned long cpsr;
int oldstatus;
/* Read the old levels and set the new ones */
+#if defined(CREATIVE_ZVM) && defined(BOOTLOADER)
+// FIXME: This workaround is for a problem with inlining;
+// for some reason 'mask' gets treated as a variable/non-immediate constant
+// but only on this build. All others (including the nearly-identical mrobe500boot) are fine
+ asm volatile (
+ "mrs %1, cpsr \n"
+ "bic %0, %1, %[mask] \n"
+ "orr %0, %0, %2 \n"
+ "msr cpsr_c, %0 \n"
+ : "=&r,r"(cpsr), "=&r,r"(oldstatus)
+ : "r,i"(status & mask), [mask]"r,i"(mask));
+#else
asm volatile (
"mrs %1, cpsr \n"
"bic %0, %1, %[mask] \n"
@@ -117,7 +129,7 @@ static inline int set_interrupt_status(int status, int mask)
"msr cpsr_c, %0 \n"
: "=&r,r"(cpsr), "=&r,r"(oldstatus)
: "r,i"(status & mask), [mask]"i,i"(mask));
-
+#endif
return oldstatus;
}