summaryrefslogtreecommitdiffstats
path: root/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99323.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99323.patch')
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99323.patch688
1 files changed, 688 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99323.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99323.patch
new file mode 100644
index 0000000000..38b6fa3f0e
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99323.patch
@@ -0,0 +1,688 @@
1 Vladimir Prus <vladimir@codesourcery.com>
2 Julian Brown <julian@codesourcery.com>
3
4 gcc/
5 * config/arm/arm.c (arm_override_options): Warn if mlow-irq-latency is
6 specified in Thumb mode.
7 (load_multiple_sequence): Return 0 if low irq latency is requested.
8 (store_multiple_sequence): Likewise.
9 (arm_gen_load_multiple): Load registers one-by-one if low irq latency
10 is requested.
11 (arm_gen_store_multiple): Likewise.
12 (vfp_output_fldmd): When low_irq_latency is non zero, pop each
13 register separately.
14 (vfp_emit_fstmd): When low_irq_latency is non zero, save each register
15 separately.
16 (arm_get_vfp_saved_size): Adjust saved register size calculation for
17 the above changes.
18 (print_pop_reg_by_ldr): New.
19 (arm_output_epilogue): Use print_pop_reg_by_ldr when low irq latency
20 is requested.
21 (emit_multi_reg_push): Push registers separately if low irq latency
22 is requested.
23 * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Set __low_irq_latency__.
24 (low_irq_latency): Define.
25 (USE_RETURN_INSN): Don't use return insn when low irq latency is
26 requested.
27 * config/arm/lib1funcs.asm (do_pop, do_push): Define as variadic
28 macros. When __low_irq_latency__ is defined, push and pop registers
29 individually.
30 (div0): Use correct punctuation.
31 * config/arm/ieee754-df.S: Adjust syntax of using do_push.
32 * config/arm/ieee754-sf.S: Likewise.
33 * config/arm/bpabi.S: Likewise.
34 * config/arm/arm.opt (mlow-irq-latency): New option.
35 * config/arm/predicates.md (load_multiple_operation): Return false is
36 low irq latency is requested.
37 (store_multiple_operation): Likewise.
38 * config/arm/arm.md (movmemqi): Don't use it if low irq latency is
39 requested.
40 * doc/invoke.texi (-mlow-irq-latency): Add documentation.
41
422010-07-26 Julian Brown <julian@codesourcery.com>
43
44 Merge from Sourcery G++ 4.4:
45
46 2007-06-06 Joseph Myers <joseph@codesourcery.com>
47
48 gcc/
49
50=== modified file 'gcc/config/arm/arm.c'
51--- old/gcc/config/arm/arm.c 2010-08-05 14:33:31 +0000
52+++ new/gcc/config/arm/arm.c 2010-08-05 15:20:54 +0000
53@@ -1884,6 +1884,13 @@
54
55 /* Register global variables with the garbage collector. */
56 arm_add_gc_roots ();
57+
58+ if (low_irq_latency && TARGET_THUMB)
59+ {
60+ warning (0,
61+ "-mlow-irq-latency has no effect when compiling for Thumb");
62+ low_irq_latency = 0;
63+ }
64 }
65
66 static void
67@@ -9053,6 +9060,9 @@
68 int base_reg = -1;
69 int i;
70
71+ if (low_irq_latency)
72+ return 0;
73+
74 /* Can only handle 2, 3, or 4 insns at present,
75 though could be easily extended if required. */
76 gcc_assert (nops >= 2 && nops <= 4);
77@@ -9282,6 +9292,9 @@
78 int base_reg = -1;
79 int i;
80
81+ if (low_irq_latency)
82+ return 0;
83+
84 /* Can only handle 2, 3, or 4 insns at present, though could be easily
85 extended if required. */
86 gcc_assert (nops >= 2 && nops <= 4);
87@@ -9489,7 +9502,7 @@
88
89 As a compromise, we use ldr for counts of 1 or 2 regs, and ldm
90 for counts of 3 or 4 regs. */
91- if (arm_tune_xscale && count <= 2 && ! optimize_size)
92+ if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size))
93 {
94 rtx seq;
95
96@@ -9552,7 +9565,7 @@
97
98 /* See arm_gen_load_multiple for discussion of
99 the pros/cons of ldm/stm usage for XScale. */
100- if (arm_tune_xscale && count <= 2 && ! optimize_size)
101+ if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size))
102 {
103 rtx seq;
104
105@@ -11795,6 +11808,21 @@
106 vfp_output_fldmd (FILE * stream, unsigned int base, int reg, int count)
107 {
108 int i;
109+ int offset;
110+
111+ if (low_irq_latency)
112+ {
113+ /* Output a sequence of FLDD instructions. */
114+ offset = 0;
115+ for (i = reg; i < reg + count; ++i, offset += 8)
116+ {
117+ fputc ('\t', stream);
118+ asm_fprintf (stream, "fldd\td%d, [%r,#%d]\n", i, base, offset);
119+ }
120+ asm_fprintf (stream, "\tadd\tsp, sp, #%d\n", count * 8);
121+ return;
122+ }
123+
124
125 /* Workaround ARM10 VFPr1 bug. */
126 if (count == 2 && !arm_arch6)
127@@ -11865,6 +11893,56 @@
128 rtx tmp, reg;
129 int i;
130
131+ if (low_irq_latency)
132+ {
133+ int saved_size;
134+ rtx sp_insn;
135+
136+ if (!count)
137+ return 0;
138+
139+ saved_size = count * GET_MODE_SIZE (DFmode);
140+
141+ /* Since fstd does not have postdecrement addressing mode,
142+ we first decrement stack pointer and then use base+offset
143+ stores for VFP registers. The ARM EABI unwind information
144+ can't easily describe base+offset loads, so we attach
145+ a note for the effects of the whole block in the first insn,
146+ and avoid marking the subsequent instructions
147+ with RTX_FRAME_RELATED_P. */
148+ sp_insn = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
149+ GEN_INT (-saved_size));
150+ sp_insn = emit_insn (sp_insn);
151+ RTX_FRAME_RELATED_P (sp_insn) = 1;
152+
153+ dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
154+ XVECEXP (dwarf, 0, 0) =
155+ gen_rtx_SET (VOIDmode, stack_pointer_rtx,
156+ plus_constant (stack_pointer_rtx, -saved_size));
157+
158+ /* push double VFP registers to stack */
159+ for (i = 0; i < count; ++i )
160+ {
161+ rtx reg;
162+ rtx mem;
163+ rtx addr;
164+ rtx insn;
165+ reg = gen_rtx_REG (DFmode, base_reg + 2*i);
166+ addr = (i == 0) ? stack_pointer_rtx
167+ : gen_rtx_PLUS (SImode, stack_pointer_rtx,
168+ GEN_INT (i * GET_MODE_SIZE (DFmode)));
169+ mem = gen_frame_mem (DFmode, addr);
170+ insn = emit_move_insn (mem, reg);
171+ XVECEXP (dwarf, 0, i+1) =
172+ gen_rtx_SET (VOIDmode, mem, reg);
173+ }
174+
175+ REG_NOTES (sp_insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
176+ REG_NOTES (sp_insn));
177+
178+ return saved_size;
179+ }
180+
181 /* Workaround ARM10 VFPr1 bug. Data corruption can occur when exactly two
182 register pairs are stored by a store multiple insn. We avoid this
183 by pushing an extra pair. */
184@@ -13307,7 +13385,7 @@
185 if (count > 0)
186 {
187 /* Workaround ARM10 VFPr1 bug. */
188- if (count == 2 && !arm_arch6)
189+ if (count == 2 && !arm_arch6 && !low_irq_latency)
190 count++;
191 saved += count * 8;
192 }
193@@ -13645,6 +13723,41 @@
194
195 }
196
197+/* Generate to STREAM a code sequence that pops registers identified
198+ in REGS_MASK from SP. SP is incremented as the result.
199+*/
200+static void
201+print_pop_reg_by_ldr (FILE *stream, int regs_mask, int rfe)
202+{
203+ int reg;
204+
205+ gcc_assert (! (regs_mask & (1 << SP_REGNUM)));
206+
207+ for (reg = 0; reg < PC_REGNUM; ++reg)
208+ if (regs_mask & (1 << reg))
209+ asm_fprintf (stream, "\tldr\t%r, [%r], #4\n",
210+ reg, SP_REGNUM);
211+
212+ if (regs_mask & (1 << PC_REGNUM))
213+ {
214+ if (rfe)
215+ /* When returning from exception, we need to
216+ copy SPSR to CPSR. There are two ways to do
217+ that: the ldm instruction with "^" suffix,
218+ and movs instruction. The latter would
219+ require that we load from stack to some
220+ scratch register, and then move to PC.
221+ Therefore, we'd need extra instruction and
222+ have to make sure we actually have a spare
223+ register. Using ldm with a single register
224+ is simler. */
225+ asm_fprintf (stream, "\tldm\tsp!, {pc}^\n");
226+ else
227+ asm_fprintf (stream, "\tldr\t%r, [%r], #4\n",
228+ PC_REGNUM, SP_REGNUM);
229+ }
230+}
231+
232 const char *
233 arm_output_epilogue (rtx sibling)
234 {
235@@ -14018,22 +14131,19 @@
236 to load use the LDR instruction - it is faster. For Thumb-2
237 always use pop and the assembler will pick the best instruction.*/
238 if (TARGET_ARM && saved_regs_mask == (1 << LR_REGNUM)
239- && !IS_INTERRUPT(func_type))
240+ && !IS_INTERRUPT (func_type))
241 {
242 asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
243 }
244 else if (saved_regs_mask)
245 {
246- if (saved_regs_mask & (1 << SP_REGNUM))
247- /* Note - write back to the stack register is not enabled
248- (i.e. "ldmfd sp!..."). We know that the stack pointer is
249- in the list of registers and if we add writeback the
250- instruction becomes UNPREDICTABLE. */
251- print_multi_reg (f, "ldmfd\t%r, ", SP_REGNUM, saved_regs_mask,
252- rfe);
253- else if (TARGET_ARM)
254- print_multi_reg (f, "ldmfd\t%r!, ", SP_REGNUM, saved_regs_mask,
255- rfe);
256+ gcc_assert ( ! (saved_regs_mask & (1 << SP_REGNUM)));
257+ if (TARGET_ARM)
258+ if (low_irq_latency)
259+ print_pop_reg_by_ldr (f, saved_regs_mask, rfe);
260+ else
261+ print_multi_reg (f, "ldmfd\t%r!, ", SP_REGNUM, saved_regs_mask,
262+ rfe);
263 else
264 print_multi_reg (f, "pop\t", SP_REGNUM, saved_regs_mask, 0);
265 }
266@@ -14154,6 +14264,32 @@
267
268 gcc_assert (num_regs && num_regs <= 16);
269
270+ if (low_irq_latency)
271+ {
272+ rtx insn = 0;
273+
274+ /* Emit a series of ldr instructions rather rather than a single ldm. */
275+ /* TODO: Use ldrd where possible. */
276+ gcc_assert (! (mask & (1 << SP_REGNUM)));
277+
278+ for (i = LAST_ARM_REGNUM; i >= 0; --i)
279+ {
280+ if (mask & (1 << i))
281+
282+ {
283+ rtx reg, where, mem;
284+
285+ reg = gen_rtx_REG (SImode, i);
286+ where = gen_rtx_PRE_DEC (SImode, stack_pointer_rtx);
287+ mem = gen_rtx_MEM (SImode, where);
288+ insn = emit_move_insn (mem, reg);
289+ RTX_FRAME_RELATED_P (insn) = 1;
290+ }
291+ }
292+
293+ return insn;
294+ }
295+
296 /* We don't record the PC in the dwarf frame information. */
297 num_dwarf_regs = num_regs;
298 if (mask & (1 << PC_REGNUM))
299
300=== modified file 'gcc/config/arm/arm.h'
301--- old/gcc/config/arm/arm.h 2010-08-05 14:33:31 +0000
302+++ new/gcc/config/arm/arm.h 2010-08-05 15:20:54 +0000
303@@ -101,6 +101,8 @@
304 builtin_define ("__ARM_PCS"); \
305 builtin_define ("__ARM_EABI__"); \
306 } \
307+ if (low_irq_latency) \
308+ builtin_define ("__low_irq_latency__"); \
309 } while (0)
310
311 /* The various ARM cores. */
312@@ -449,6 +451,10 @@
313 /* Nonzero if chip supports integer division instruction. */
314 extern int arm_arch_hwdiv;
315
316+/* Nonzero if we should minimize interrupt latency of the
317+ generated code. */
318+extern int low_irq_latency;
319+
320 #ifndef TARGET_DEFAULT
321 #define TARGET_DEFAULT (MASK_APCS_FRAME)
322 #endif
323@@ -1823,9 +1829,10 @@
324 /* Determine if the epilogue should be output as RTL.
325 You should override this if you define FUNCTION_EXTRA_EPILOGUE. */
326 /* This is disabled for Thumb-2 because it will confuse the
327- conditional insn counter. */
328+ conditional insn counter.
329+ Do not use a return insn if we're avoiding ldm/stm instructions. */
330 #define USE_RETURN_INSN(ISCOND) \
331- (TARGET_ARM ? use_return_insn (ISCOND, NULL) : 0)
332+ ((TARGET_ARM && !low_irq_latency) ? use_return_insn (ISCOND, NULL) : 0)
333
334 /* Definitions for register eliminations.
335
336
337=== modified file 'gcc/config/arm/arm.md'
338--- old/gcc/config/arm/arm.md 2010-08-05 12:06:40 +0000
339+++ new/gcc/config/arm/arm.md 2010-08-05 15:20:54 +0000
340@@ -6587,7 +6587,7 @@
341 (match_operand:BLK 1 "general_operand" "")
342 (match_operand:SI 2 "const_int_operand" "")
343 (match_operand:SI 3 "const_int_operand" "")]
344- "TARGET_EITHER"
345+ "TARGET_EITHER && !low_irq_latency"
346 "
347 if (TARGET_32BIT)
348 {
349
350=== modified file 'gcc/config/arm/arm.opt'
351--- old/gcc/config/arm/arm.opt 2009-06-18 11:24:10 +0000
352+++ new/gcc/config/arm/arm.opt 2010-08-05 15:20:54 +0000
353@@ -161,6 +161,10 @@
354 Target Report Mask(NEON_VECTORIZE_QUAD)
355 Use Neon quad-word (rather than double-word) registers for vectorization
356
357+mlow-irq-latency
358+Target Report Var(low_irq_latency)
359+Try to reduce interrupt latency of the generated code
360+
361 mword-relocations
362 Target Report Var(target_word_relocations) Init(TARGET_DEFAULT_WORD_RELOCATIONS)
363 Only generate absolute relocations on word sized values.
364
365=== modified file 'gcc/config/arm/bpabi.S'
366--- old/gcc/config/arm/bpabi.S 2009-12-17 15:37:23 +0000
367+++ new/gcc/config/arm/bpabi.S 2010-08-05 15:20:54 +0000
368@@ -116,16 +116,17 @@
369 test_div_by_zero signed
370
371 sub sp, sp, #8
372-#if defined(__thumb2__)
373+/* Low latency and Thumb-2 do_push implementations can't push sp directly. */
374+#if defined(__thumb2__) || defined(__irq_low_latency__)
375 mov ip, sp
376- push {ip, lr}
377+ do_push (ip, lr)
378 #else
379- do_push {sp, lr}
380+ stmfd sp!, {sp, lr}
381 #endif
382 bl SYM(__gnu_ldivmod_helper) __PLT__
383 ldr lr, [sp, #4]
384 add sp, sp, #8
385- do_pop {r2, r3}
386+ do_pop (r2, r3)
387 RET
388
389 #endif /* L_aeabi_ldivmod */
390@@ -136,16 +137,17 @@
391 test_div_by_zero unsigned
392
393 sub sp, sp, #8
394-#if defined(__thumb2__)
395+/* Low latency and Thumb-2 do_push implementations can't push sp directly. */
396+#if defined(__thumb2__) || defined(__irq_low_latency__)
397 mov ip, sp
398- push {ip, lr}
399+ do_push (ip, lr)
400 #else
401- do_push {sp, lr}
402+ stmfd sp!, {sp, lr}
403 #endif
404 bl SYM(__gnu_uldivmod_helper) __PLT__
405 ldr lr, [sp, #4]
406 add sp, sp, #8
407- do_pop {r2, r3}
408+ do_pop (r2, r3)
409 RET
410
411 #endif /* L_aeabi_divmod */
412
413=== modified file 'gcc/config/arm/ieee754-df.S'
414--- old/gcc/config/arm/ieee754-df.S 2009-06-05 12:52:36 +0000
415+++ new/gcc/config/arm/ieee754-df.S 2010-08-05 15:20:54 +0000
416@@ -83,7 +83,7 @@
417 ARM_FUNC_START adddf3
418 ARM_FUNC_ALIAS aeabi_dadd adddf3
419
420-1: do_push {r4, r5, lr}
421+1: do_push (r4, r5, lr)
422
423 @ Look for zeroes, equal values, INF, or NAN.
424 shift1 lsl, r4, xh, #1
425@@ -427,7 +427,7 @@
426 do_it eq, t
427 moveq r1, #0
428 RETc(eq)
429- do_push {r4, r5, lr}
430+ do_push (r4, r5, lr)
431 mov r4, #0x400 @ initial exponent
432 add r4, r4, #(52-1 - 1)
433 mov r5, #0 @ sign bit is 0
434@@ -447,7 +447,7 @@
435 do_it eq, t
436 moveq r1, #0
437 RETc(eq)
438- do_push {r4, r5, lr}
439+ do_push (r4, r5, lr)
440 mov r4, #0x400 @ initial exponent
441 add r4, r4, #(52-1 - 1)
442 ands r5, r0, #0x80000000 @ sign bit in r5
443@@ -481,7 +481,7 @@
444 RETc(eq) @ we are done already.
445
446 @ value was denormalized. We can normalize it now.
447- do_push {r4, r5, lr}
448+ do_push (r4, r5, lr)
449 mov r4, #0x380 @ setup corresponding exponent
450 and r5, xh, #0x80000000 @ move sign bit in r5
451 bic xh, xh, #0x80000000
452@@ -508,9 +508,9 @@
453 @ compatibility.
454 adr ip, LSYM(f0_ret)
455 @ Push pc as well so that RETLDM works correctly.
456- do_push {r4, r5, ip, lr, pc}
457+ do_push (r4, r5, ip, lr, pc)
458 #else
459- do_push {r4, r5, lr}
460+ do_push (r4, r5, lr)
461 #endif
462
463 mov r5, #0
464@@ -534,9 +534,9 @@
465 @ compatibility.
466 adr ip, LSYM(f0_ret)
467 @ Push pc as well so that RETLDM works correctly.
468- do_push {r4, r5, ip, lr, pc}
469+ do_push (r4, r5, ip, lr, pc)
470 #else
471- do_push {r4, r5, lr}
472+ do_push (r4, r5, lr)
473 #endif
474
475 ands r5, ah, #0x80000000 @ sign bit in r5
476@@ -585,7 +585,7 @@
477 @ Legacy code expects the result to be returned in f0. Copy it
478 @ there as well.
479 LSYM(f0_ret):
480- do_push {r0, r1}
481+ do_push (r0, r1)
482 ldfd f0, [sp], #8
483 RETLDM
484
485@@ -602,7 +602,7 @@
486
487 ARM_FUNC_START muldf3
488 ARM_FUNC_ALIAS aeabi_dmul muldf3
489- do_push {r4, r5, r6, lr}
490+ do_push (r4, r5, r6, lr)
491
492 @ Mask out exponents, trap any zero/denormal/INF/NAN.
493 mov ip, #0xff
494@@ -910,7 +910,7 @@
495 ARM_FUNC_START divdf3
496 ARM_FUNC_ALIAS aeabi_ddiv divdf3
497
498- do_push {r4, r5, r6, lr}
499+ do_push (r4, r5, r6, lr)
500
501 @ Mask out exponents, trap any zero/denormal/INF/NAN.
502 mov ip, #0xff
503@@ -1195,7 +1195,7 @@
504
505 @ The status-returning routines are required to preserve all
506 @ registers except ip, lr, and cpsr.
507-6: do_push {r0, lr}
508+6: do_push (r0, lr)
509 ARM_CALL cmpdf2
510 @ Set the Z flag correctly, and the C flag unconditionally.
511 cmp r0, #0
512
513=== modified file 'gcc/config/arm/ieee754-sf.S'
514--- old/gcc/config/arm/ieee754-sf.S 2009-06-05 12:52:36 +0000
515+++ new/gcc/config/arm/ieee754-sf.S 2010-08-05 15:20:54 +0000
516@@ -481,7 +481,7 @@
517 and r3, ip, #0x80000000
518
519 @ Well, no way to make it shorter without the umull instruction.
520- do_push {r3, r4, r5}
521+ do_push (r3, r4, r5)
522 mov r4, r0, lsr #16
523 mov r5, r1, lsr #16
524 bic r0, r0, r4, lsl #16
525@@ -492,7 +492,7 @@
526 mla r0, r4, r1, r0
527 adds r3, r3, r0, lsl #16
528 adc r1, ip, r0, lsr #16
529- do_pop {r0, r4, r5}
530+ do_pop (r0, r4, r5)
531
532 #else
533
534@@ -882,7 +882,7 @@
535
536 @ The status-returning routines are required to preserve all
537 @ registers except ip, lr, and cpsr.
538-6: do_push {r0, r1, r2, r3, lr}
539+6: do_push (r0, r1, r2, r3, lr)
540 ARM_CALL cmpsf2
541 @ Set the Z flag correctly, and the C flag unconditionally.
542 cmp r0, #0
543
544=== modified file 'gcc/config/arm/lib1funcs.asm'
545--- old/gcc/config/arm/lib1funcs.asm 2010-04-02 18:54:46 +0000
546+++ new/gcc/config/arm/lib1funcs.asm 2010-08-05 15:20:54 +0000
547@@ -254,8 +254,8 @@
548 .macro shift1 op, arg0, arg1, arg2
549 \op \arg0, \arg1, \arg2
550 .endm
551-#define do_push push
552-#define do_pop pop
553+#define do_push(...) push {__VA_ARGS__}
554+#define do_pop(...) pop {__VA_ARGS__}
555 #define COND(op1, op2, cond) op1 ## op2 ## cond
556 /* Perform an arithmetic operation with a variable shift operand. This
557 requires two instructions and a scratch register on Thumb-2. */
558@@ -269,8 +269,42 @@
559 .macro shift1 op, arg0, arg1, arg2
560 mov \arg0, \arg1, \op \arg2
561 .endm
562-#define do_push stmfd sp!,
563-#define do_pop ldmfd sp!,
564+#if defined(__low_irq_latency__)
565+#define do_push(...) \
566+ _buildN1(do_push, _buildC1(__VA_ARGS__))( __VA_ARGS__)
567+#define _buildN1(BASE, X) _buildN2(BASE, X)
568+#define _buildN2(BASE, X) BASE##X
569+#define _buildC1(...) _buildC2(__VA_ARGS__,9,8,7,6,5,4,3,2,1)
570+#define _buildC2(a1,a2,a3,a4,a5,a6,a7,a8,a9,c,...) c
571+
572+#define do_push1(r1) str r1, [sp, #-4]!
573+#define do_push2(r1, r2) str r2, [sp, #-4]! ; str r1, [sp, #-4]!
574+#define do_push3(r1, r2, r3) str r3, [sp, #-4]! ; str r2, [sp, #-4]!; str r1, [sp, #-4]!
575+#define do_push4(r1, r2, r3, r4) \
576+ do_push3 (r2, r3, r4);\
577+ do_push1 (r1)
578+#define do_push5(r1, r2, r3, r4, r5) \
579+ do_push4 (r2, r3, r4, r5);\
580+ do_push1 (r1)
581+
582+#define do_pop(...) \
583+_buildN1(do_pop, _buildC1(__VA_ARGS__))( __VA_ARGS__)
584+
585+#define do_pop1(r1) ldr r1, [sp], #4
586+#define do_pop2(r1, r2) ldr r1, [sp], #4 ; ldr r2, [sp], #4
587+#define do_pop3(r1, r2, r3) ldr r1, [sp], #4 ; str r2, [sp], #4; str r3, [sp], #4
588+#define do_pop4(r1, r2, r3, r4) \
589+ do_pop1 (r1);\
590+ do_pup3 (r2, r3, r4)
591+#define do_pop5(r1, r2, r3, r4, r5) \
592+ do_pop1 (r1);\
593+ do_pop4 (r2, r3, r4, r5)
594+#else
595+#define do_push(...) stmfd sp!, { __VA_ARGS__}
596+#define do_pop(...) ldmfd sp!, {__VA_ARGS__}
597+#endif
598+
599+
600 #define COND(op1, op2, cond) op1 ## cond ## op2
601 .macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp
602 \name \dest, \src1, \src2, \shiftop \shiftreg
603@@ -1260,7 +1294,7 @@
604 ARM_FUNC_START div0
605 #endif
606
607- do_push {r1, lr}
608+ do_push (r1, lr)
609 mov r0, #SIGFPE
610 bl SYM(raise) __PLT__
611 RETLDM r1
612@@ -1277,7 +1311,7 @@
613 #if defined __ARM_EABI__ && defined __linux__
614 @ EABI GNU/Linux call to cacheflush syscall.
615 ARM_FUNC_START clear_cache
616- do_push {r7}
617+ do_push (r7)
618 #if __ARM_ARCH__ >= 7 || defined(__ARM_ARCH_6T2__)
619 movw r7, #2
620 movt r7, #0xf
621@@ -1287,7 +1321,7 @@
622 #endif
623 mov r2, #0
624 swi 0
625- do_pop {r7}
626+ do_pop (r7)
627 RET
628 FUNC_END clear_cache
629 #else
630@@ -1490,7 +1524,7 @@
631 push {r4, lr}
632 # else
633 ARM_FUNC_START clzdi2
634- do_push {r4, lr}
635+ do_push (r4, lr)
636 # endif
637 cmp xxh, #0
638 bne 1f
639
640=== modified file 'gcc/config/arm/predicates.md'
641--- old/gcc/config/arm/predicates.md 2010-07-30 14:17:05 +0000
642+++ new/gcc/config/arm/predicates.md 2010-08-05 15:20:54 +0000
643@@ -328,6 +328,9 @@
644 HOST_WIDE_INT i = 1, base = 0;
645 rtx elt;
646
647+ if (low_irq_latency)
648+ return false;
649+
650 if (count <= 1
651 || GET_CODE (XVECEXP (op, 0, 0)) != SET)
652 return false;
653@@ -385,6 +388,9 @@
654 HOST_WIDE_INT i = 1, base = 0;
655 rtx elt;
656
657+ if (low_irq_latency)
658+ return false;
659+
660 if (count <= 1
661 || GET_CODE (XVECEXP (op, 0, 0)) != SET)
662 return false;
663
664=== modified file 'gcc/doc/invoke.texi'
665--- old/gcc/doc/invoke.texi 2010-07-29 17:03:20 +0000
666+++ new/gcc/doc/invoke.texi 2010-08-05 15:20:54 +0000
667@@ -469,6 +469,7 @@
668 -mtpcs-frame -mtpcs-leaf-frame @gol
669 -mcaller-super-interworking -mcallee-super-interworking @gol
670 -mtp=@var{name} @gol
671+-mlow-irq-latency @gol
672 -mword-relocations @gol
673 -mfix-cortex-m3-ldrd}
674
675@@ -9489,6 +9490,12 @@
676 @code{,}, @code{!}, @code{|}, and @code{*} as needed.
677
678
679+@item -mlow-irq-latency
680+@opindex mlow-irq-latency
681+Avoid instructions with high interrupt latency when generating
682+code. This can increase code size and reduce performance.
683+The option is off by default.
684+
685 @end table
686
687 The conditional text @code{X} in a %@{@code{S}:@code{X}@} or similar
688