arm-ldmstm.ml: Set "predicable_short_it" to "no" where appropriate.
[gcc.git] / gcc / config / arm / arm-ldmstm.ml
1 (* Auto-generate ARM ldm/stm patterns
2 Copyright (C) 2010-2013 Free Software Foundation, Inc.
3 Contributed by CodeSourcery.
4
5 This file is part of GCC.
6
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
10 version.
11
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
15 for more details.
16
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/>.
20
21 This is an O'Caml program. The O'Caml compiler is available from:
22
23 http://caml.inria.fr/
24
25 Or from your favourite OS's friendly packaging system. Tested with version
26 3.09.2, though other versions will probably work too.
27
28 Run with:
29 ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.md
30 *)
31
32 type amode = IA | IB | DA | DB
33
34 type optype = IN | OUT | INOUT
35
36 let rec string_of_addrmode addrmode =
37 match addrmode with
38 IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
39
40 let rec initial_offset addrmode nregs =
41 match addrmode with
42 IA -> 0
43 | IB -> 4
44 | DA -> -4 * nregs + 4
45 | DB -> -4 * nregs
46
47 let rec final_offset addrmode nregs =
48 match addrmode with
49 IA -> nregs * 4
50 | IB -> nregs * 4
51 | DA -> -4 * nregs
52 | DB -> -4 * nregs
53
54 let constr thumb =
55 if thumb then "l" else "rk"
56
57 let inout_constr op_type =
58 match op_type with
59 OUT -> "=&"
60 | INOUT -> "+&"
61 | IN -> ""
62
63 let destreg nregs first op_type thumb =
64 if not first then
65 Printf.sprintf "(match_dup %d)" (nregs + 1)
66 else
67 Printf.sprintf ("(match_operand:SI %d \"s_register_operand\" \"%s%s\")")
68 (nregs + 1) (inout_constr op_type) (constr thumb)
69
70 let write_ldm_set thumb nregs offset opnr first =
71 let indent = " " in
72 Printf.printf "%s" (if first then " [" else indent);
73 Printf.printf "(set (match_operand:SI %d \"arm_hard_register_operand\" \"\")\n" opnr;
74 Printf.printf "%s (mem:SI " indent;
75 begin if offset != 0 then Printf.printf "(plus:SI " end;
76 Printf.printf "%s" (destreg nregs first IN thumb);
77 begin if offset != 0 then Printf.printf "\n%s (const_int %d))" indent offset end;
78 Printf.printf "))"
79
80 let write_stm_set thumb nregs offset opnr first =
81 let indent = " " in
82 Printf.printf "%s" (if first then " [" else indent);
83 Printf.printf "(set (mem:SI ";
84 begin if offset != 0 then Printf.printf "(plus:SI " end;
85 Printf.printf "%s" (destreg nregs first IN thumb);
86 begin if offset != 0 then Printf.printf " (const_int %d))" offset end;
87 Printf.printf ")\n%s (match_operand:SI %d \"arm_hard_register_operand\" \"\"))" indent opnr
88
89 let write_ldm_peep_set extra_indent nregs opnr first =
90 let indent = " " ^ extra_indent in
91 Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
92 Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
93 Printf.printf "%s (match_operand:SI %d \"memory_operand\" \"\"))" indent (nregs + opnr)
94
95 let write_stm_peep_set extra_indent nregs opnr first =
96 let indent = " " ^ extra_indent in
97 Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
98 Printf.printf "(set (match_operand:SI %d \"memory_operand\" \"\")\n" (nregs + opnr);
99 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\"))" indent opnr
100
101 let write_any_load optype nregs opnr first =
102 let indent = " " in
103 Printf.printf "%s" (if first then " [" else indent);
104 Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
105 Printf.printf "%s (match_operand:SI %d \"%s\" \"\"))" indent (nregs * 2 + opnr) optype
106
107 let write_const_store nregs opnr first =
108 let indent = " " in
109 Printf.printf "%s(set (match_operand:SI %d \"memory_operand\" \"\")\n" indent (nregs + opnr);
110 Printf.printf "%s (match_dup %d))" indent opnr
111
112 let write_const_stm_peep_set nregs opnr first =
113 write_any_load "const_int_operand" nregs opnr first;
114 Printf.printf "\n";
115 write_const_store nregs opnr false
116
117
118 let rec write_pat_sets func opnr offset first n_left =
119 func offset opnr first;
120 begin
121 if n_left > 1 then begin
122 Printf.printf "\n";
123 write_pat_sets func (opnr + 1) (offset + 4) false (n_left - 1);
124 end else
125 Printf.printf "]"
126 end
127
128 let rec write_peep_sets func opnr first n_left =
129 func opnr first;
130 begin
131 if n_left > 1 then begin
132 Printf.printf "\n";
133 write_peep_sets func (opnr + 1) false (n_left - 1);
134 end
135 end
136
137 let can_thumb addrmode update is_store =
138 match addrmode, update, is_store with
139 (* Thumb1 mode only supports IA with update. However, for LDMIA,
140 if the address register also appears in the list of loaded
141 registers, the loaded value is stored, hence the RTL pattern
142 to describe such an insn does not have an update. We check
143 in the match_parallel predicate that the condition described
144 above is met. *)
145 IA, _, false -> true
146 | IA, true, true -> true
147 | _ -> false
148
149 exception InvalidAddrMode of string;;
150
151 let target addrmode thumb =
152 match addrmode, thumb with
153 IA, true -> "TARGET_THUMB1"
154 | IA, false -> "TARGET_32BIT"
155 | DB, false -> "TARGET_32BIT"
156 | _, false -> "TARGET_ARM"
157 | _, _ -> raise (InvalidAddrMode "ERROR: Invalid Addressing mode for Thumb1.")
158
159 let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
160 let astr = string_of_addrmode addrmode in
161 Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
162 (if thumb then "thumb_" else "") name nregs astr
163 (if update then "_update" else "");
164 Printf.printf " [(match_parallel 0 \"%s_multiple_operation\"\n" ls;
165 begin
166 if update then begin
167 Printf.printf " [(set %s\n (plus:SI %s"
168 (destreg nregs true INOUT thumb) (destreg nregs false IN thumb);
169 Printf.printf " (const_int %d)))\n"
170 (final_offset addrmode nregs)
171 end
172 end;
173 write_pat_sets
174 (write_set_fn thumb nregs) 1
175 (initial_offset addrmode nregs)
176 (not update) nregs;
177 Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
178 (target addrmode thumb)
179 (if update then nregs + 1 else nregs);
180 Printf.printf " \"%s%%(%s%%)\\t%%%d%s, {"
181 name astr (nregs + 1) (if update then "!" else "");
182 for n = 1 to nregs; do
183 Printf.printf "%%%d%s" n (if n < nregs then ", " else "")
184 done;
185 Printf.printf "}\"\n";
186 Printf.printf " [(set_attr \"type\" \"%s%d\")" ls nregs;
187 if not thumb then begin
188 Printf.printf "\n (set_attr \"predicable\" \"yes\")";
189 if addrmode == IA || addrmode == DB then
190 Printf.printf "\n (set_attr \"predicable_short_it\" \"no\")";
191 end;
192 Printf.printf "])\n\n"
193
194 let write_ldm_pattern addrmode nregs update =
195 write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update false;
196 begin if can_thumb addrmode update false then
197 write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update true;
198 end
199
200 let write_stm_pattern addrmode nregs update =
201 write_pattern_1 "stm" "store" addrmode nregs write_stm_set update false;
202 begin if can_thumb addrmode update true then
203 write_pattern_1 "stm" "store" addrmode nregs write_stm_set update true;
204 end
205
206 let write_ldm_commutative_peephole thumb =
207 let nregs = 2 in
208 Printf.printf "(define_peephole2\n";
209 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
210 let indent = " " in
211 if thumb then begin
212 Printf.printf "\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
213 Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
214 Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
215 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
216 end else begin
217 Printf.printf "\n%s(parallel\n" indent;
218 Printf.printf "%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
219 Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
220 Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
221 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
222 Printf.printf "%s (clobber (reg:CC CC_REGNUM))])]\n" indent
223 end;
224 Printf.printf " \"((((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 2);
225 Printf.printf " && (REGNO (operands[%d]) == REGNO (operands[1])))\n" (nregs * 2 + 3);
226 Printf.printf " || ((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 3);
227 Printf.printf " && (REGNO (operands[%d]) == REGNO (operands[1]))))\n" (nregs * 2 + 2);
228 Printf.printf " && (peep2_regno_dead_p (%d, REGNO (operands[0]))\n" (nregs + 1);
229 Printf.printf " || (REGNO (operands[0]) == REGNO (operands[%d])))\n" (nregs * 2);
230 Printf.printf " && (peep2_regno_dead_p (%d, REGNO (operands[1]))\n" (nregs + 1);
231 Printf.printf " || (REGNO (operands[1]) == REGNO (operands[%d]))))\"\n" (nregs * 2);
232 begin
233 if thumb then
234 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
235 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
236 else begin
237 Printf.printf " [(parallel\n";
238 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
239 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
240 Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
241 end
242 end;
243 Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
244 Printf.printf "})\n\n"
245
246 let write_ldm_peephole nregs =
247 Printf.printf "(define_peephole2\n";
248 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
249 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
250 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
251
252 let write_ldm_peephole_b nregs =
253 if nregs > 2 then begin
254 Printf.printf "(define_peephole2\n";
255 write_ldm_peep_set "" nregs 0 true;
256 Printf.printf "\n (parallel\n";
257 write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
258 Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
259 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
260 end
261
262 let write_stm_peephole nregs =
263 Printf.printf "(define_peephole2\n";
264 write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
265 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
266 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
267
268 let write_stm_peephole_b nregs =
269 if nregs > 2 then begin
270 Printf.printf "(define_peephole2\n";
271 write_stm_peep_set "" nregs 0 true;
272 Printf.printf "\n (parallel\n";
273 write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
274 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
275 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
276 end
277
278 let write_const_stm_peephole_a nregs =
279 Printf.printf "(define_peephole2\n";
280 write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
281 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
282 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
283
284 let write_const_stm_peephole_b nregs =
285 Printf.printf "(define_peephole2\n";
286 write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
287 Printf.printf "\n";
288 write_peep_sets (write_const_store nregs) 0 false nregs;
289 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
290 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
291
292 let patterns () =
293 let addrmodes = [ IA; IB; DA; DB ] in
294 let sizes = [ 4; 3; 2] in
295 List.iter
296 (fun n ->
297 List.iter
298 (fun addrmode ->
299 write_ldm_pattern addrmode n false;
300 write_ldm_pattern addrmode n true;
301 write_stm_pattern addrmode n false;
302 write_stm_pattern addrmode n true)
303 addrmodes;
304 write_ldm_peephole n;
305 write_ldm_peephole_b n;
306 write_const_stm_peephole_a n;
307 write_const_stm_peephole_b n;
308 write_stm_peephole n;)
309 sizes;
310 write_ldm_commutative_peephole false;
311 write_ldm_commutative_peephole true
312
313 let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
314
315 (* Do it. *)
316
317 let _ =
318 print_lines [
319 "/* ARM ldm/stm instruction patterns. This file was automatically generated";
320 " using arm-ldmstm.ml. Please do not edit manually.";
321 "";
322 " Copyright (C) 2010-2013 Free Software Foundation, Inc.";
323 " Contributed by CodeSourcery.";
324 "";
325 " This file is part of GCC.";
326 "";
327 " GCC is free software; you can redistribute it and/or modify it";
328 " under the terms of the GNU General Public License as published";
329 " by the Free Software Foundation; either version 3, or (at your";
330 " option) any later version.";
331 "";
332 " GCC is distributed in the hope that it will be useful, but WITHOUT";
333 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
334 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
335 " License for more details.";
336 "";
337 " You should have received a copy of the GNU General Public License and";
338 " a copy of the GCC Runtime Library Exception along with this program;";
339 " see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
340 " <http://www.gnu.org/licenses/>. */";
341 ""];
342 patterns ();