1 (* Auto-generate ARM ldm/stm patterns
2 Copyright (C) 2010-2013 Free Software Foundation, Inc.
3 Contributed by CodeSourcery.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>.
21 This is an O'Caml program. The O'Caml compiler is available from:
25 Or from your favourite OS's friendly packaging system. Tested with version
26 3.09.2, though other versions will probably work too.
29 ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.md
32 type amode
= IA
| IB
| DA
| DB
34 type optype
= IN
| OUT
| INOUT
36 let rec string_of_addrmode addrmode
=
38 IA
-> "ia" | IB
-> "ib" | DA
-> "da" | DB
-> "db"
40 let rec initial_offset addrmode nregs
=
44 | DA
-> -4 * nregs
+ 4
47 let rec final_offset addrmode nregs
=
55 if thumb
then "l" else "rk"
57 let inout_constr op_type
=
63 let destreg nregs first op_type thumb
=
65 Printf.sprintf
"(match_dup %d)" (nregs
+ 1)
67 Printf.sprintf
("(match_operand:SI %d \"s_register_operand\" \"%s%s\")")
68 (nregs
+ 1) (inout_constr op_type
) (constr thumb
)
70 let reg_predicate thumb
=
71 if thumb
then "low_register_operand" else "arm_hard_general_register_operand"
73 let write_ldm_set thumb nregs offset opnr first
=
75 Printf.printf
"%s" (if first
then " [" else indent);
76 Printf.printf
"(set (match_operand:SI %d \"%s\" \"\")\n" opnr
(reg_predicate thumb
);
77 Printf.printf
"%s (mem:SI " indent;
78 begin if offset
!= 0 then Printf.printf
"(plus:SI " end;
79 Printf.printf
"%s" (destreg nregs first IN thumb
);
80 begin if offset
!= 0 then Printf.printf
"\n%s (const_int %d))" indent offset
end;
83 let write_stm_set thumb nregs offset opnr first
=
85 Printf.printf
"%s" (if first
then " [" else indent);
86 Printf.printf
"(set (mem:SI ";
87 begin if offset
!= 0 then Printf.printf
"(plus:SI " end;
88 Printf.printf
"%s" (destreg nregs first IN thumb
);
89 begin if offset
!= 0 then Printf.printf
" (const_int %d))" offset
end;
90 Printf.printf
")\n%s (match_operand:SI %d \"%s\" \"\"))" indent opnr
(reg_predicate thumb
)
92 let write_ldm_peep_set extra_indent nregs opnr first
=
93 let indent = " " ^ extra_indent
in
94 Printf.printf
"%s" (if first
then extra_indent ^
" [" else indent);
95 Printf.printf
"(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr
;
96 Printf.printf
"%s (match_operand:SI %d \"memory_operand\" \"\"))" indent (nregs
+ opnr
)
98 let write_stm_peep_set extra_indent nregs opnr first
=
99 let indent = " " ^ extra_indent
in
100 Printf.printf
"%s" (if first
then extra_indent ^
" [" else indent);
101 Printf.printf
"(set (match_operand:SI %d \"memory_operand\" \"\")\n" (nregs
+ opnr
);
102 Printf.printf
"%s (match_operand:SI %d \"s_register_operand\" \"\"))" indent opnr
104 let write_any_load optype nregs opnr first
=
106 Printf.printf
"%s" (if first
then " [" else indent);
107 Printf.printf
"(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr
;
108 Printf.printf
"%s (match_operand:SI %d \"%s\" \"\"))" indent (nregs
* 2 + opnr
) optype
110 let write_const_store nregs opnr first
=
112 Printf.printf
"%s(set (match_operand:SI %d \"memory_operand\" \"\")\n" indent (nregs
+ opnr
);
113 Printf.printf
"%s (match_dup %d))" indent opnr
115 let write_const_stm_peep_set nregs opnr first
=
116 write_any_load "const_int_operand" nregs opnr first
;
118 write_const_store nregs opnr
false
121 let rec write_pat_sets func opnr offset first n_left
=
122 func offset opnr first
;
124 if n_left
> 1 then begin
126 write_pat_sets func
(opnr
+ 1) (offset
+ 4) false (n_left
- 1);
131 let rec write_peep_sets func opnr first n_left
=
134 if n_left
> 1 then begin
136 write_peep_sets func
(opnr
+ 1) false (n_left
- 1);
140 let can_thumb addrmode update is_store
=
141 match addrmode
, update
, is_store
with
142 (* Thumb1 mode only supports IA with update. However, for LDMIA,
143 if the address register also appears in the list of loaded
144 registers, the loaded value is stored, hence the RTL pattern
145 to describe such an insn does not have an update. We check
146 in the match_parallel predicate that the condition described
149 | IA
, true, true -> true
152 exception InvalidAddrMode
of string;;
154 let target addrmode thumb
=
155 match addrmode
, thumb
with
156 IA
, true -> "TARGET_THUMB1"
157 | IA
, false -> "TARGET_32BIT"
158 | DB
, false -> "TARGET_32BIT"
159 | _
, false -> "TARGET_ARM"
160 | _
, _
-> raise
(InvalidAddrMode
"ERROR: Invalid Addressing mode for Thumb1.")
162 let write_pattern_1 name ls addrmode nregs write_set_fn update thumb
=
163 let astr = string_of_addrmode addrmode
in
164 Printf.printf
"(define_insn \"*%s%s%d_%s%s\"\n"
165 (if thumb
then "thumb_" else "") name nregs
astr
166 (if update
then "_update" else "");
167 Printf.printf
" [(match_parallel 0 \"%s_multiple_operation\"\n" ls
;
170 Printf.printf
" [(set %s\n (plus:SI %s"
171 (destreg nregs
true INOUT thumb
) (destreg nregs
false IN thumb
);
172 Printf.printf
" (const_int %d)))\n"
173 (final_offset addrmode nregs
)
177 (write_set_fn thumb nregs
) 1
178 (initial_offset addrmode nregs
)
180 Printf.printf
")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
181 (target addrmode thumb
)
182 (if update
then nregs
+ 1 else nregs
);
183 Printf.printf
" \"%s%%(%s%%)\\t%%%d%s, {"
184 name
astr (nregs
+ 1) (if update
then "!" else "");
185 for n
= 1 to nregs
; do
186 Printf.printf
"%%%d%s" n
(if n
< nregs
then ", " else "")
188 Printf.printf
"}\"\n";
189 Printf.printf
" [(set_attr \"type\" \"%s%d\")" ls nregs
;
190 if not thumb
then begin
191 Printf.printf
"\n (set_attr \"predicable\" \"yes\")";
192 if addrmode
== IA
|| addrmode
== DB
then
193 Printf.printf
"\n (set_attr \"predicable_short_it\" \"no\")";
195 Printf.printf
"])\n\n"
197 let write_ldm_pattern addrmode nregs update
=
198 write_pattern_1 "ldm" "load" addrmode nregs
write_ldm_set update
false;
199 begin if can_thumb addrmode update
false then
200 write_pattern_1 "ldm" "load" addrmode nregs
write_ldm_set update
true;
203 let write_stm_pattern addrmode nregs update
=
204 write_pattern_1 "stm" "store" addrmode nregs
write_stm_set update
false;
205 begin if can_thumb addrmode update
true then
206 write_pattern_1 "stm" "store" addrmode nregs
write_stm_set update
true;
209 let write_ldm_commutative_peephole thumb
=
211 Printf.printf
"(define_peephole2\n";
212 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
215 Printf.printf
"\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
216 Printf.printf
"%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
217 Printf.printf
"%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
218 Printf.printf
"%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
220 Printf.printf
"\n%s(parallel\n" indent;
221 Printf.printf
"%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
222 Printf.printf
"%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
223 Printf.printf
"%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
224 Printf.printf
"%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
225 Printf.printf
"%s (clobber (reg:CC CC_REGNUM))])]\n" indent
227 Printf.printf
" \"((((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 2);
228 Printf.printf
" && (REGNO (operands[%d]) == REGNO (operands[1])))\n" (nregs * 2 + 3);
229 Printf.printf
" || ((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 3);
230 Printf.printf
" && (REGNO (operands[%d]) == REGNO (operands[1]))))\n" (nregs * 2 + 2);
231 Printf.printf
" && (peep2_regno_dead_p (%d, REGNO (operands[0]))\n" (nregs + 1);
232 Printf.printf
" || (REGNO (operands[0]) == REGNO (operands[%d])))\n" (nregs * 2);
233 Printf.printf
" && (peep2_regno_dead_p (%d, REGNO (operands[1]))\n" (nregs + 1);
234 Printf.printf
" || (REGNO (operands[1]) == REGNO (operands[%d]))))\"\n" (nregs * 2);
237 Printf.printf
" [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
238 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
240 Printf.printf
" [(parallel\n";
241 Printf.printf
" [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
242 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
243 Printf.printf
" (clobber (reg:CC CC_REGNUM))])]\n"
246 Printf.printf
"{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
247 Printf.printf
"})\n\n"
249 let write_ldm_peephole nregs =
250 Printf.printf
"(define_peephole2\n";
251 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
252 Printf.printf
"]\n \"\"\n [(const_int 0)]\n{\n";
253 Printf.printf
" if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
255 let write_ldm_peephole_b nregs =
256 if nregs > 2 then begin
257 Printf.printf
"(define_peephole2\n";
258 write_ldm_peep_set "" nregs 0 true;
259 Printf.printf
"\n (parallel\n";
260 write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
261 Printf.printf
"])]\n \"\"\n [(const_int 0)]\n{\n";
262 Printf.printf
" if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
265 let write_stm_peephole nregs =
266 Printf.printf
"(define_peephole2\n";
267 write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
268 Printf.printf
"]\n \"\"\n [(const_int 0)]\n{\n";
269 Printf.printf
" if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
271 let write_stm_peephole_b nregs =
272 if nregs > 2 then begin
273 Printf.printf
"(define_peephole2\n";
274 write_stm_peep_set "" nregs 0 true;
275 Printf.printf
"\n (parallel\n";
276 write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
277 Printf.printf
"]\n \"\"\n [(const_int 0)]\n{\n";
278 Printf.printf
" if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
281 let write_const_stm_peephole_a nregs =
282 Printf.printf
"(define_peephole2\n";
283 write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
284 Printf.printf
"]\n \"\"\n [(const_int 0)]\n{\n";
285 Printf.printf
" if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
287 let write_const_stm_peephole_b nregs =
288 Printf.printf
"(define_peephole2\n";
289 write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
291 write_peep_sets (write_const_store nregs) 0 false nregs;
292 Printf.printf
"]\n \"\"\n [(const_int 0)]\n{\n";
293 Printf.printf
" if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
296 let addrmodes = [ IA
; IB
; DA
; DB
] in
297 let sizes = [ 4; 3; 2] in
302 write_ldm_pattern addrmode n
false;
303 write_ldm_pattern addrmode n
true;
304 write_stm_pattern addrmode n
false;
305 write_stm_pattern addrmode n
true)
307 write_ldm_peephole n
;
308 write_ldm_peephole_b n
;
309 write_const_stm_peephole_a n
;
310 write_const_stm_peephole_b n
;
311 write_stm_peephole n
;)
313 write_ldm_commutative_peephole false;
314 write_ldm_commutative_peephole true
316 let print_lines = List.iter
(fun s
-> Format.printf
"%s@\n" s
)
322 "/* ARM ldm/stm instruction patterns. This file was automatically generated";
323 " using arm-ldmstm.ml. Please do not edit manually.";
325 " Copyright (C) 2010-2013 Free Software Foundation, Inc.";
326 " Contributed by CodeSourcery.";
328 " This file is part of GCC.";
330 " GCC is free software; you can redistribute it and/or modify it";
331 " under the terms of the GNU General Public License as published";
332 " by the Free Software Foundation; either version 3, or (at your";
333 " option) any later version.";
335 " GCC is distributed in the hope that it will be useful, but WITHOUT";
336 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
337 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
338 " License for more details.";
340 " You should have received a copy of the GNU General Public License and";
341 " a copy of the GCC Runtime Library Exception along with this program;";
342 " see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
343 " <http://www.gnu.org/licenses/>. */";