+2016-05-12 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/70830
+ * config/arm/arm.c (arm_output_multireg_pop): Avoid POP instruction
+ when popping the PC and within an interrupt handler routine.
+ Add missing tab to output of "ldmfd".
+ (output_return_instruction): Output LDMFD with SP update rather
+ than POP when returning from interrupt handler.
+
2016-05-12 Jakub Jelinek <jakub@redhat.com>
* config/i386/i386.md (isa): Add x64_avx512dq, enable if
int num_saves = XVECLEN (operands[0], 0);
unsigned int regno;
unsigned int regno_base = REGNO (operands[1]);
+ bool interrupt_p = IS_INTERRUPT (arm_current_func_type ());
offset = 0;
offset += update ? 1 : 0;
}
conditional = reverse ? "%?%D0" : "%?%d0";
- if ((regno_base == SP_REGNUM) && update)
+ /* Can't use POP if returning from an interrupt. */
+ if ((regno_base == SP_REGNUM) && !(interrupt_p && return_pc))
{
sprintf (pattern, "pop%s\t{", conditional);
}
/* Output ldmfd when the base register is SP, otherwise output ldmia.
It's just a convention, their semantics are identical. */
if (regno_base == SP_REGNUM)
- /* update is never true here, hence there is no need to handle
- pop here. */
- sprintf (pattern, "ldmfd%s", conditional);
-
- if (update)
+ sprintf (pattern, "ldmfd%s\t", conditional);
+ else if (update)
sprintf (pattern, "ldmia%s\t", conditional);
else
sprintf (pattern, "ldm%s\t", conditional);
strcat (pattern, "}");
- if (IS_INTERRUPT (arm_current_func_type ()) && return_pc)
+ if (interrupt_p && return_pc)
strcat (pattern, "^");
output_asm_insn (pattern, &cond);
sprintf (instr, "ldmfd%s\t%%|sp, {", conditional);
}
}
+ /* For interrupt returns we have to use an LDM rather than
+ a POP so that we can use the exception return variant. */
+ else if (IS_INTERRUPT (func_type))
+ sprintf (instr, "ldmfd%s\t%%|sp!, {", conditional);
else
- sprintf (instr, "pop%s\t{", conditional);
+ sprintf (instr, "pop%s\t{", conditional);
p = instr + strlen (instr);
+2016-05-12 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/70830
+ * gcc.target/arm/interrupt-1.c: Change dg-compile to dg-assemble.
+ Add -save-temps to dg-options.
+ Scan for ldmfd rather than pop instruction.
+ * gcc.target/arm/interrupt-2.c: Likewise.
+ * gcc.target/arm/pr70830.c: New test.
+
2016-05-12 Jakub Jelinek <jakub@redhat.com>
* gcc.target/i386/avx512bw-vpextr-1.c: New test.
/* Verify that prologue and epilogue are correct for functions with
__attribute__ ((interrupt)). */
-/* { dg-do compile } */
+/* { dg-do assemble } */
/* { dg-require-effective-target arm_nothumb } */
-/* { dg-options "-O0 -marm" } */
+/* { dg-options "-O0 -marm -save-temps" } */
/* This test is not valid when -mthumb. */
extern void bar (int);
}
/* { dg-final { scan-assembler "push\t{r0, r1, r2, r3, r4, fp, ip, lr}" } } */
-/* { dg-final { scan-assembler "pop\t{r0, r1, r2, r3, r4, fp, ip, pc}\\^" } } */
+/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, r4, fp, ip, pc}\\^" } } */
/* Verify that prologue and epilogue are correct for functions with
__attribute__ ((interrupt)). */
-/* { dg-do compile } */
+/* { dg-do assemble } */
/* { dg-require-effective-target arm_nothumb } */
-/* { dg-options "-O1 -marm" } */
+/* { dg-options "-O1 -marm -save-temps" } */
/* This test is not valid when -mthumb. */
extern void bar (int);
}
/* { dg-final { scan-assembler "push\t{r0, r1, r2, r3, r4, r5, ip, lr}" } } */
-/* { dg-final { scan-assembler "pop\t{r0, r1, r2, r3, r4, r5, ip, pc}\\^" } } */
+/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, r4, r5, ip, pc}\\^" } } */
--- /dev/null
+/* PR target/70830. */
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_arm_ok } */
+/* { dg-options "-Os -marm -save-temps" } */
+
+/* This test is not valid when -mthumb. */
+
+extern void prints (char *);
+
+void __attribute__ ((interrupt ("IRQ"))) dm3730_IRQHandler(void)
+{
+ prints("IRQ" );
+}
+/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, ip, pc}\\^" } } */