summaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch734
1 files changed, 734 insertions, 0 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch
new file mode 100644
index 0000000000..cb434082bf
--- /dev/null
+++ b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch
@@ -0,0 +1,734 @@
12010-10-22 Julian Brown <julian@codesourcery.com>
2
3 Backport from mainline:
4
5 2010-10-18 Marcus Shawcroft <marcus.shawcroft@arm.com>
6
7 gcc/testsuite/
8 * gcc.target/arm/synchronize.c: Permit dmb or mcr in assembler scan.
9
102010-10-14 Julian Brown <julian@codesourcery.com>
11
12 Backport from mainline:
13
14 2010-08-18 Marcus Shawcroft <marcus.shawcroft@arm.com>
15
16 gcc/
17 * config/arm/arm-protos.h (arm_expand_sync): New.
18 (arm_output_memory_barrier, arm_output_sync_insn): New.
19 (arm_sync_loop_insns): New.
20 * config/arm/arm.c (FL_ARCH7): New.
21 (FL_FOR_ARCH7): Include FL_ARCH7.
22 (arm_arch7): New.
23 (arm_print_operand): Support %C markup.
24 (arm_legitimize_sync_memory): New.
25 (arm_emit, arm_insn_count, arm_count, arm_output_asm_insn): New.
26 (arm_process_output_memory_barrier, arm_output_memory_barrier): New.
27 (arm_ldrex_suffix, arm_output_ldrex, arm_output_strex): New.
28 (arm_output_op2, arm_output_op3, arm_output_sync_loop): New.
29 (arm_get_sync_operand, FETCH_SYNC_OPERAND): New.
30 (arm_process_output_sync_insn, arm_output_sync_insn): New.
31 (arm_sync_loop_insns,arm_call_generator, arm_expand_sync): New.
32 * config/arm/arm.h (struct arm_sync_generator): New.
33 (TARGET_HAVE_DMB, TARGET_HAVE_DMB_MCR): New.
34 (TARGET_HAVE_MEMORY_BARRIER): New.
35 (TARGET_HAVE_LDREX, TARGET_HAVE_LDREXBHD): New.
36 * config/arm/arm.md: Include sync.md.
37 (UNSPEC_MEMORY_BARRIER): New.
38 (VUNSPEC_SYNC_COMPARE_AND_SWAP, VUNSPEC_SYNC_LOCK): New.
39 (VUNSPEC_SYNC_OP):New.
40 (VUNSPEC_SYNC_NEW_OP, VUNSPEC_SYNC_OLD_OP): New.
41 (sync_result, sync_memory, sync_required_value): New attributes.
42 (sync_new_value, sync_t1, sync_t2): Likewise.
43 (sync_release_barrier, sync_op): Likewise.
44 (length): Add logic to length attribute defintion to call
45 arm_sync_loop_insns when appropriate.
46 * config/arm/sync.md: New file.
47
48 2010-09-02 Marcus Shawcroft <marcus.shawcroft@arm.com>
49
50 gcc/
51 * config/arm/predicates.md (arm_sync_memory_operand): New.
52 * config/arm/sync.md (arm_sync_compare_and_swapsi): Change predicate
53 to arm_sync_memory_operand and constraint to Q.
54 (arm_sync_compare_and_swap<mode>): Likewise.
55 (arm_sync_compare_and_swap<mode>): Likewise.
56 (arm_sync_lock_test_and_setsi): Likewise.
57 (arm_sync_lock_test_and_set<mode>): Likewise.
58 (arm_sync_new_<sync_optab>si): Likewise.
59 (arm_sync_new_nandsi): Likewise.
60 (arm_sync_new_<sync_optab><mode>): Likewise.
61 (arm_sync_new_nand<mode>): Likewise.
62 (arm_sync_old_<sync_optab>si): Likewise.
63 (arm_sync_old_nandsi): Likewise.
64 (arm_sync_old_<sync_optab><mode>): Likewise.
65 (arm_sync_old_nand<mode>): Likewise.
66
67 2010-09-13 Marcus Shawcroft <marcus.shawcroft@arm.com>
68
69 gcc/
70 * config/arm/arm.md: (define_attr "conds"): Update comment.
71 * config/arm/sync.md (arm_sync_compare_and_swapsi): Change
72 conds attribute to clob.
73 (arm_sync_compare_and_swapsi): Likewise.
74 (arm_sync_compare_and_swap<mode>): Likewise.
75 (arm_sync_lock_test_and_setsi): Likewise.
76 (arm_sync_lock_test_and_set<mode>): Likewise.
77 (arm_sync_new_<sync_optab>si): Likewise.
78 (arm_sync_new_nandsi): Likewise.
79 (arm_sync_new_<sync_optab><mode>): Likewise.
80 (arm_sync_new_nand<mode>): Likewise.
81 (arm_sync_old_<sync_optab>si): Likewise.
82 (arm_sync_old_nandsi): Likewise.
83 (arm_sync_old_<sync_optab><mode>): Likewise.
84 (arm_sync_old_nand<mode>): Likewise.
85
86 2010-09-13 Marcus Shawcroft <marcus.shawcroft@arm.com>
87
88 gcc/testsuite/
89 * gcc.target/arm/sync-1.c: New.
90
91
92 Backport from FSF:
93
94 gcc/
95 2010-08-18 Marcus Shawcroft <marcus.shawcroft@arm.com>
96 * config/arm/arm-protos.h (arm_expand_sync): New.
97 (arm_output_memory_barrier, arm_output_sync_insn): New.
98 (arm_sync_loop_insns): New.
99 * config/arm/arm.c (FL_ARCH7): New.
100 (FL_FOR_ARCH7): Include FL_ARCH7.
101 (arm_arch7): New.
102 (arm_print_operand): Support %C markup.
103 (arm_legitimize_sync_memory): New.
104 (arm_emit, arm_insn_count, arm_count, arm_output_asm_insn): New.
105 (arm_process_output_memory_barrier, arm_output_memory_barrier): New.
106 (arm_ldrex_suffix, arm_output_ldrex, arm_output_strex): New.
107 (arm_output_op2, arm_output_op3, arm_output_sync_loop): New.
108 (arm_get_sync_operand, FETCH_SYNC_OPERAND): New.
109 (arm_process_output_sync_insn, arm_output_sync_insn): New.
110 (arm_sync_loop_insns,arm_call_generator, arm_expand_sync): New.
111 * config/arm/arm.h (struct arm_sync_generator): New.
112 (TARGET_HAVE_DMB, TARGET_HAVE_DMB_MCR): New.
113 (TARGET_HAVE_MEMORY_BARRIER): New.
114 (TARGET_HAVE_LDREX, TARGET_HAVE_LDREXBHD): New.
115 * config/arm/arm.md: Include sync.md.
116 (UNSPEC_MEMORY_BARRIER): New.
117 (VUNSPEC_SYNC_COMPARE_AND_SWAP, VUNSPEC_SYNC_LOCK): New.
118 (VUNSPEC_SYNC_OP):New.
119 (VUNSPEC_SYNC_NEW_OP, VUNSPEC_SYNC_OLD_OP): New.
120 (sync_result, sync_memory, sync_required_value): New attributes.
121 (sync_new_value, sync_t1, sync_t2): Likewise.
122 (sync_release_barrier, sync_op): Likewise.
123 (length): Add logic to length attribute defintion to call
124 arm_sync_loop_insns when appropriate.
125 * config/arm/sync.md: New file.
126
127 gcc/
128 2010-09-02 Marcus Shawcroft <marcus.shawcroft@arm.com>
129 * config/arm/predicates.md (arm_sync_memory_operand): New.
130 * config/arm/sync.md (arm_sync_compare_and_swapsi): Change predicate
131 to arm_sync_memory_operand and constraint to Q.
132 (arm_sync_compare_and_swap<mode>): Likewise.
133 (arm_sync_compare_and_swap<mode>): Likewise.
134 (arm_sync_lock_test_and_setsi): Likewise.
135 (arm_sync_lock_test_and_set<mode>): Likewise.
136 (arm_sync_new_<sync_optab>si): Likewise.
137 (arm_sync_new_nandsi): Likewise.
138 (arm_sync_new_<sync_optab><mode>): Likewise.
139 (arm_sync_new_nand<mode>): Likewise.
140 (arm_sync_old_<sync_optab>si): Likewise.
141 (arm_sync_old_nandsi): Likewise.
142 (arm_sync_old_<sync_optab><mode>): Likewise.
143 (arm_sync_old_nand<mode>): Likewise.
144
145=== modified file 'gcc/config/arm/arm-protos.h'
146Index: gcc-4.5/gcc/config/arm/arm-protos.h
147===================================================================
148--- gcc-4.5.orig/gcc/config/arm/arm-protos.h
149+++ gcc-4.5/gcc/config/arm/arm-protos.h
150@@ -151,6 +151,11 @@ extern const char *vfp_output_fstmd (rtx
151 extern void arm_set_return_address (rtx, rtx);
152 extern int arm_eliminable_register (rtx);
153 extern const char *arm_output_shift(rtx *, int);
154+extern void arm_expand_sync (enum machine_mode, struct arm_sync_generator *,
155+ rtx, rtx, rtx, rtx);
156+extern const char *arm_output_memory_barrier (rtx *);
157+extern const char *arm_output_sync_insn (rtx, rtx *);
158+extern unsigned int arm_sync_loop_insns (rtx , rtx *);
159
160 extern bool arm_output_addr_const_extra (FILE *, rtx);
161
162Index: gcc-4.5/gcc/config/arm/arm.c
163===================================================================
164--- gcc-4.5.orig/gcc/config/arm/arm.c
165+++ gcc-4.5/gcc/config/arm/arm.c
166@@ -602,6 +602,7 @@ static int thumb_call_reg_needed;
167 #define FL_NEON (1 << 20) /* Neon instructions. */
168 #define FL_ARCH7EM (1 << 21) /* Instructions present in the ARMv7E-M
169 architecture. */
170+#define FL_ARCH7 (1 << 22) /* Architecture 7. */
171
172 #define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */
173
174@@ -626,7 +627,7 @@ static int thumb_call_reg_needed;
175 #define FL_FOR_ARCH6ZK FL_FOR_ARCH6K
176 #define FL_FOR_ARCH6T2 (FL_FOR_ARCH6 | FL_THUMB2)
177 #define FL_FOR_ARCH6M (FL_FOR_ARCH6 & ~FL_NOTM)
178-#define FL_FOR_ARCH7 (FL_FOR_ARCH6T2 &~ FL_NOTM)
179+#define FL_FOR_ARCH7 ((FL_FOR_ARCH6T2 & ~FL_NOTM) | FL_ARCH7)
180 #define FL_FOR_ARCH7A (FL_FOR_ARCH7 | FL_NOTM | FL_ARCH6K)
181 #define FL_FOR_ARCH7R (FL_FOR_ARCH7A | FL_DIV)
182 #define FL_FOR_ARCH7M (FL_FOR_ARCH7 | FL_DIV)
183@@ -664,6 +665,9 @@ int arm_arch6 = 0;
184 /* Nonzero if this chip supports the ARM 6K extensions. */
185 int arm_arch6k = 0;
186
187+/* Nonzero if this chip supports the ARM 7 extensions. */
188+int arm_arch7 = 0;
189+
190 /* Nonzero if instructions not present in the 'M' profile can be used. */
191 int arm_arch_notm = 0;
192
193@@ -1602,6 +1606,7 @@ arm_override_options (void)
194 arm_arch6 = (insn_flags & FL_ARCH6) != 0;
195 arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
196 arm_arch_notm = (insn_flags & FL_NOTM) != 0;
197+ arm_arch7 = (insn_flags & FL_ARCH7) != 0;
198 arm_arch7em = (insn_flags & FL_ARCH7EM) != 0;
199 arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0;
200 arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
201@@ -16562,6 +16567,17 @@ arm_print_operand (FILE *stream, rtx x,
202 }
203 return;
204
205+ case 'C':
206+ {
207+ rtx addr;
208+
209+ gcc_assert (GET_CODE (x) == MEM);
210+ addr = XEXP (x, 0);
211+ gcc_assert (GET_CODE (addr) == REG);
212+ asm_fprintf (stream, "[%r]", REGNO (addr));
213+ }
214+ return;
215+
216 /* Translate an S register number into a D register number and element index. */
217 case 'y':
218 {
219@@ -22793,4 +22809,372 @@ arm_builtin_support_vector_misalignment
220 is_packed);
221 }
222
223+/* Legitimize a memory reference for sync primitive implemented using
224+ ldrex / strex. We currently force the form of the reference to be
225+ indirect without offset. We do not yet support the indirect offset
226+ addressing supported by some ARM targets for these
227+ instructions. */
228+static rtx
229+arm_legitimize_sync_memory (rtx memory)
230+{
231+ rtx addr = force_reg (Pmode, XEXP (memory, 0));
232+ rtx legitimate_memory = gen_rtx_MEM (GET_MODE (memory), addr);
233+
234+ set_mem_alias_set (legitimate_memory, ALIAS_SET_MEMORY_BARRIER);
235+ MEM_VOLATILE_P (legitimate_memory) = MEM_VOLATILE_P (memory);
236+ return legitimate_memory;
237+}
238+
239+/* An instruction emitter. */
240+typedef void (* emit_f) (int label, const char *, rtx *);
241+
242+/* An instruction emitter that emits via the conventional
243+ output_asm_insn. */
244+static void
245+arm_emit (int label ATTRIBUTE_UNUSED, const char *pattern, rtx *operands)
246+{
247+ output_asm_insn (pattern, operands);
248+}
249+
250+/* Count the number of emitted synchronization instructions. */
251+static unsigned arm_insn_count;
252+
253+/* An emitter that counts emitted instructions but does not actually
254+ emit instruction into the the instruction stream. */
255+static void
256+arm_count (int label,
257+ const char *pattern ATTRIBUTE_UNUSED,
258+ rtx *operands ATTRIBUTE_UNUSED)
259+{
260+ if (! label)
261+ ++ arm_insn_count;
262+}
263+
264+/* Construct a pattern using conventional output formatting and feed
265+ it to output_asm_insn. Provides a mechanism to construct the
266+ output pattern on the fly. Note the hard limit on the pattern
267+ buffer size. */
268+static void
269+arm_output_asm_insn (emit_f emit, int label, rtx *operands,
270+ const char *pattern, ...)
271+{
272+ va_list ap;
273+ char buffer[256];
274+
275+ va_start (ap, pattern);
276+ vsprintf (buffer, pattern, ap);
277+ va_end (ap);
278+ emit (label, buffer, operands);
279+}
280+
281+/* Emit the memory barrier instruction, if any, provided by this
282+ target to a specified emitter. */
283+static void
284+arm_process_output_memory_barrier (emit_f emit, rtx *operands)
285+{
286+ if (TARGET_HAVE_DMB)
287+ {
288+ /* Note we issue a system level barrier. We should consider
289+ issuing a inner shareabilty zone barrier here instead, ie.
290+ "DMB ISH". */
291+ emit (0, "dmb\tsy", operands);
292+ return;
293+ }
294+
295+ if (TARGET_HAVE_DMB_MCR)
296+ {
297+ emit (0, "mcr\tp15, 0, r0, c7, c10, 5", operands);
298+ return;
299+ }
300+
301+ gcc_unreachable ();
302+}
303+
304+/* Emit the memory barrier instruction, if any, provided by this
305+ target. */
306+const char *
307+arm_output_memory_barrier (rtx *operands)
308+{
309+ arm_process_output_memory_barrier (arm_emit, operands);
310+ return "";
311+}
312+
313+/* Helper to figure out the instruction suffix required on ldrex/strex
314+ for operations on an object of the specified mode. */
315+static const char *
316+arm_ldrex_suffix (enum machine_mode mode)
317+{
318+ switch (mode)
319+ {
320+ case QImode: return "b";
321+ case HImode: return "h";
322+ case SImode: return "";
323+ case DImode: return "d";
324+ default:
325+ gcc_unreachable ();
326+ }
327+ return "";
328+}
329+
330+/* Emit an ldrex{b,h,d, } instruction appropriate for the specified
331+ mode. */
332+static void
333+arm_output_ldrex (emit_f emit,
334+ enum machine_mode mode,
335+ rtx target,
336+ rtx memory)
337+{
338+ const char *suffix = arm_ldrex_suffix (mode);
339+ rtx operands[2];
340+
341+ operands[0] = target;
342+ operands[1] = memory;
343+ arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix);
344+}
345+
346+/* Emit a strex{b,h,d, } instruction appropriate for the specified
347+ mode. */
348+static void
349+arm_output_strex (emit_f emit,
350+ enum machine_mode mode,
351+ const char *cc,
352+ rtx result,
353+ rtx value,
354+ rtx memory)
355+{
356+ const char *suffix = arm_ldrex_suffix (mode);
357+ rtx operands[3];
358+
359+ operands[0] = result;
360+ operands[1] = value;
361+ operands[2] = memory;
362+ arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2", suffix,
363+ cc);
364+}
365+
366+/* Helper to emit a two operand instruction. */
367+static void
368+arm_output_op2 (emit_f emit, const char *mnemonic, rtx d, rtx s)
369+{
370+ rtx operands[2];
371+
372+ operands[0] = d;
373+ operands[1] = s;
374+ arm_output_asm_insn (emit, 0, operands, "%s\t%%0, %%1", mnemonic);
375+}
376+
377+/* Helper to emit a three operand instruction. */
378+static void
379+arm_output_op3 (emit_f emit, const char *mnemonic, rtx d, rtx a, rtx b)
380+{
381+ rtx operands[3];
382+
383+ operands[0] = d;
384+ operands[1] = a;
385+ operands[2] = b;
386+ arm_output_asm_insn (emit, 0, operands, "%s\t%%0, %%1, %%2", mnemonic);
387+}
388+
389+/* Emit a load store exclusive synchronization loop.
390+
391+ do
392+ old_value = [mem]
393+ if old_value != required_value
394+ break;
395+ t1 = sync_op (old_value, new_value)
396+ [mem] = t1, t2 = [0|1]
397+ while ! t2
398+
399+ Note:
400+ t1 == t2 is not permitted
401+ t1 == old_value is permitted
402+
403+ required_value:
404+
405+ RTX register or const_int representing the required old_value for
406+ the modify to continue, if NULL no comparsion is performed. */
407+static void
408+arm_output_sync_loop (emit_f emit,
409+ enum machine_mode mode,
410+ rtx old_value,
411+ rtx memory,
412+ rtx required_value,
413+ rtx new_value,
414+ rtx t1,
415+ rtx t2,
416+ enum attr_sync_op sync_op,
417+ int early_barrier_required)
418+{
419+ rtx operands[1];
420+
421+ gcc_assert (t1 != t2);
422+
423+ if (early_barrier_required)
424+ arm_process_output_memory_barrier (emit, NULL);
425+
426+ arm_output_asm_insn (emit, 1, operands, "%sLSYT%%=:", LOCAL_LABEL_PREFIX);
427+
428+ arm_output_ldrex (emit, mode, old_value, memory);
429+
430+ if (required_value)
431+ {
432+ rtx operands[2];
433+
434+ operands[0] = old_value;
435+ operands[1] = required_value;
436+ arm_output_asm_insn (emit, 0, operands, "cmp\t%%0, %%1");
437+ arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYB%%=", LOCAL_LABEL_PREFIX);
438+ }
439+
440+ switch (sync_op)
441+ {
442+ case SYNC_OP_ADD:
443+ arm_output_op3 (emit, "add", t1, old_value, new_value);
444+ break;
445+
446+ case SYNC_OP_SUB:
447+ arm_output_op3 (emit, "sub", t1, old_value, new_value);
448+ break;
449+
450+ case SYNC_OP_IOR:
451+ arm_output_op3 (emit, "orr", t1, old_value, new_value);
452+ break;
453+
454+ case SYNC_OP_XOR:
455+ arm_output_op3 (emit, "eor", t1, old_value, new_value);
456+ break;
457+
458+ case SYNC_OP_AND:
459+ arm_output_op3 (emit,"and", t1, old_value, new_value);
460+ break;
461+
462+ case SYNC_OP_NAND:
463+ arm_output_op3 (emit, "and", t1, old_value, new_value);
464+ arm_output_op2 (emit, "mvn", t1, t1);
465+ break;
466+
467+ case SYNC_OP_NONE:
468+ t1 = new_value;
469+ break;
470+ }
471+
472+ arm_output_strex (emit, mode, "", t2, t1, memory);
473+ operands[0] = t2;
474+ arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
475+ arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=", LOCAL_LABEL_PREFIX);
476+
477+ arm_process_output_memory_barrier (emit, NULL);
478+ arm_output_asm_insn (emit, 1, operands, "%sLSYB%%=:", LOCAL_LABEL_PREFIX);
479+}
480+
481+static rtx
482+arm_get_sync_operand (rtx *operands, int index, rtx default_value)
483+{
484+ if (index > 0)
485+ default_value = operands[index - 1];
486+
487+ return default_value;
488+}
489+
490+#define FETCH_SYNC_OPERAND(NAME, DEFAULT) \
491+ arm_get_sync_operand (operands, (int) get_attr_sync_##NAME (insn), DEFAULT);
492+
493+/* Extract the operands for a synchroniztion instruction from the
494+ instructions attributes and emit the instruction. */
495+static void
496+arm_process_output_sync_insn (emit_f emit, rtx insn, rtx *operands)
497+{
498+ rtx result, memory, required_value, new_value, t1, t2;
499+ int early_barrier;
500+ enum machine_mode mode;
501+ enum attr_sync_op sync_op;
502+
503+ result = FETCH_SYNC_OPERAND(result, 0);
504+ memory = FETCH_SYNC_OPERAND(memory, 0);
505+ required_value = FETCH_SYNC_OPERAND(required_value, 0);
506+ new_value = FETCH_SYNC_OPERAND(new_value, 0);
507+ t1 = FETCH_SYNC_OPERAND(t1, 0);
508+ t2 = FETCH_SYNC_OPERAND(t2, 0);
509+ early_barrier =
510+ get_attr_sync_release_barrier (insn) == SYNC_RELEASE_BARRIER_YES;
511+ sync_op = get_attr_sync_op (insn);
512+ mode = GET_MODE (memory);
513+
514+ arm_output_sync_loop (emit, mode, result, memory, required_value,
515+ new_value, t1, t2, sync_op, early_barrier);
516+}
517+
518+/* Emit a synchronization instruction loop. */
519+const char *
520+arm_output_sync_insn (rtx insn, rtx *operands)
521+{
522+ arm_process_output_sync_insn (arm_emit, insn, operands);
523+ return "";
524+}
525+
526+/* Count the number of machine instruction that will be emitted for a
527+ synchronization instruction. Note that the emitter used does not
528+ emit instructions, it just counts instructions being carefull not
529+ to count labels. */
530+unsigned int
531+arm_sync_loop_insns (rtx insn, rtx *operands)
532+{
533+ arm_insn_count = 0;
534+ arm_process_output_sync_insn (arm_count, insn, operands);
535+ return arm_insn_count;
536+}
537+
538+/* Helper to call a target sync instruction generator, dealing with
539+ the variation in operands required by the different generators. */
540+static rtx
541+arm_call_generator (struct arm_sync_generator *generator, rtx old_value,
542+ rtx memory, rtx required_value, rtx new_value)
543+{
544+ switch (generator->op)
545+ {
546+ case arm_sync_generator_omn:
547+ gcc_assert (! required_value);
548+ return generator->u.omn (old_value, memory, new_value);
549+
550+ case arm_sync_generator_omrn:
551+ gcc_assert (required_value);
552+ return generator->u.omrn (old_value, memory, required_value, new_value);
553+ }
554+
555+ return NULL;
556+}
557+
558+/* Expand a synchronization loop. The synchronization loop is expanded
559+ as an opaque block of instructions in order to ensure that we do
560+ not subsequently get extraneous memory accesses inserted within the
561+ critical region. The exclusive access property of ldrex/strex is
562+ only guaranteed in there are no intervening memory accesses. */
563+void
564+arm_expand_sync (enum machine_mode mode,
565+ struct arm_sync_generator *generator,
566+ rtx target, rtx memory, rtx required_value, rtx new_value)
567+{
568+ if (target == NULL)
569+ target = gen_reg_rtx (mode);
570+
571+ memory = arm_legitimize_sync_memory (memory);
572+ if (mode != SImode)
573+ {
574+ rtx load_temp = gen_reg_rtx (SImode);
575+
576+ if (required_value)
577+ required_value = convert_modes (SImode, mode, required_value, true);
578+
579+ new_value = convert_modes (SImode, mode, new_value, true);
580+ emit_insn (arm_call_generator (generator, load_temp, memory,
581+ required_value, new_value));
582+ emit_move_insn (target, gen_lowpart (mode, load_temp));
583+ }
584+ else
585+ {
586+ emit_insn (arm_call_generator (generator, target, memory, required_value,
587+ new_value));
588+ }
589+}
590+
591 #include "gt-arm.h"
592Index: gcc-4.5/gcc/config/arm/arm.h
593===================================================================
594--- gcc-4.5.orig/gcc/config/arm/arm.h
595+++ gcc-4.5/gcc/config/arm/arm.h
596@@ -128,6 +128,24 @@ enum target_cpus
597 /* The processor for which instructions should be scheduled. */
598 extern enum processor_type arm_tune;
599
600+enum arm_sync_generator_tag
601+ {
602+ arm_sync_generator_omn,
603+ arm_sync_generator_omrn
604+ };
605+
606+/* Wrapper to pass around a polymorphic pointer to a sync instruction
607+ generator and. */
608+struct arm_sync_generator
609+{
610+ enum arm_sync_generator_tag op;
611+ union
612+ {
613+ rtx (* omn) (rtx, rtx, rtx);
614+ rtx (* omrn) (rtx, rtx, rtx, rtx);
615+ } u;
616+};
617+
618 typedef enum arm_cond_code
619 {
620 ARM_EQ = 0, ARM_NE, ARM_CS, ARM_CC, ARM_MI, ARM_PL, ARM_VS, ARM_VC,
621@@ -272,6 +290,20 @@ extern void (*arm_lang_output_object_att
622 for Thumb-2. */
623 #define TARGET_UNIFIED_ASM TARGET_THUMB2
624
625+/* Nonzero if this chip provides the DMB instruction. */
626+#define TARGET_HAVE_DMB (arm_arch7)
627+
628+/* Nonzero if this chip implements a memory barrier via CP15. */
629+#define TARGET_HAVE_DMB_MCR (arm_arch6k && ! TARGET_HAVE_DMB)
630+
631+/* Nonzero if this chip implements a memory barrier instruction. */
632+#define TARGET_HAVE_MEMORY_BARRIER (TARGET_HAVE_DMB || TARGET_HAVE_DMB_MCR)
633+
634+/* Nonzero if this chip supports ldrex and strex */
635+#define TARGET_HAVE_LDREX ((arm_arch6 && TARGET_ARM) || arm_arch7)
636+
637+/* Nonzero if this chip supports ldrex{bhd} and strex{bhd}. */
638+#define TARGET_HAVE_LDREXBHD ((arm_arch6k && TARGET_ARM) || arm_arch7)
639
640 /* True iff the full BPABI is being used. If TARGET_BPABI is true,
641 then TARGET_AAPCS_BASED must be true -- but the converse does not
642@@ -405,6 +437,12 @@ extern int arm_arch5e;
643 /* Nonzero if this chip supports the ARM Architecture 6 extensions. */
644 extern int arm_arch6;
645
646+/* Nonzero if this chip supports the ARM Architecture 6k extensions. */
647+extern int arm_arch6k;
648+
649+/* Nonzero if this chip supports the ARM Architecture 7 extensions. */
650+extern int arm_arch7;
651+
652 /* Nonzero if instructions not present in the 'M' profile can be used. */
653 extern int arm_arch_notm;
654
655Index: gcc-4.5/gcc/config/arm/arm.md
656===================================================================
657--- gcc-4.5.orig/gcc/config/arm/arm.md
658+++ gcc-4.5/gcc/config/arm/arm.md
659@@ -103,6 +103,7 @@
660 (UNSPEC_RBIT 26) ; rbit operation.
661 (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
662 ; another symbolic address.
663+ (UNSPEC_MEMORY_BARRIER 28) ; Represent a memory barrier.
664 ]
665 )
666
667@@ -139,6 +140,11 @@
668 (VUNSPEC_ALIGN32 16) ; Used to force 32-byte alignment.
669 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
670 ; handling.
671+ (VUNSPEC_SYNC_COMPARE_AND_SWAP 21) ; Represent an atomic compare swap.
672+ (VUNSPEC_SYNC_LOCK 22) ; Represent a sync_lock_test_and_set.
673+ (VUNSPEC_SYNC_OP 23) ; Represent a sync_<op>
674+ (VUNSPEC_SYNC_NEW_OP 24) ; Represent a sync_new_<op>
675+ (VUNSPEC_SYNC_OLD_OP 25) ; Represent a sync_old_<op>
676 ]
677 )
678
679@@ -163,8 +169,21 @@
680 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
681 (const (symbol_ref "arm_fpu_attr")))
682
683+(define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
684+(define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
685+(define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
686+(define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
687+(define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
688+(define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
689+(define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
690+(define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
691+ (const_string "none"))
692+
693 ; LENGTH of an instruction (in bytes)
694-(define_attr "length" "" (const_int 4))
695+(define_attr "length" ""
696+ (cond [(not (eq_attr "sync_memory" "none"))
697+ (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
698+ ] (const_int 4)))
699
700 ; POOL_RANGE is how far away from a constant pool entry that this insn
701 ; can be placed. If the distance is zero, then this insn will never
702@@ -11549,4 +11568,5 @@
703 (include "thumb2.md")
704 ;; Neon patterns
705 (include "neon.md")
706-
707+;; Synchronization Primitives
708+(include "sync.md")
709Index: gcc-4.5/gcc/config/arm/predicates.md
710===================================================================
711--- gcc-4.5.orig/gcc/config/arm/predicates.md
712+++ gcc-4.5/gcc/config/arm/predicates.md
713@@ -573,6 +573,11 @@
714 (and (match_test "TARGET_32BIT")
715 (match_operand 0 "arm_di_operand"))))
716
717+;; True if the operand is memory reference suitable for a ldrex/strex.
718+(define_predicate "arm_sync_memory_operand"
719+ (and (match_operand 0 "memory_operand")
720+ (match_code "reg" "0")))
721+
722 ;; Predicates for parallel expanders based on mode.
723 (define_special_predicate "vect_par_constant_high"
724 (match_code "parallel")
725Index: gcc-4.5/gcc/testsuite/gcc.target/arm/synchronize.c
726===================================================================
727--- gcc-4.5.orig/gcc/testsuite/gcc.target/arm/synchronize.c
728+++ gcc-4.5/gcc/testsuite/gcc.target/arm/synchronize.c
729@@ -1,4 +1,4 @@
730-/* { dg-final { scan-assembler "__sync_synchronize" { target arm*-*-linux-*eabi } } } */
731+/* { dg-final { scan-assembler "__sync_synchronize|dmb|mcr" { target arm*-*-linux-*eabi } } } */
732
733 void *foo (void)
734 {