2011-03-21 Daniel Jacobowitz <dan@codesourcery.com>
[official-gcc.git] / gcc / config / arm / arm-ldmstm.ml
blob221edd2aa31ac63eebde456772a0082d283b034f
1 (* Auto-generate ARM ldm/stm patterns
2 Copyright (C) 2010 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
10 version.
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.
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:
23 http://caml.inria.fr/
25 Or from your favourite OS's friendly packaging system. Tested with version
26 3.09.2, though other versions will probably work too.
28 Run with:
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 =
37 match addrmode with
38 IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
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
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
54 let constr thumb =
55 if thumb then "l" else "rk"
57 let inout_constr op_type =
58 match op_type with
59 OUT -> "=&"
60 | INOUT -> "+&"
61 | IN -> ""
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)
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 "))"
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
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)
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
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
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
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
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 "]"
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);
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
149 let target addrmode thumb =
150 match addrmode, thumb with
151 IA, true -> "TARGET_THUMB1"
152 | IA, false -> "TARGET_32BIT"
153 | DB, false -> "TARGET_32BIT"
154 | _, false -> "TARGET_ARM"
156 let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
157 let astr = string_of_addrmode addrmode in
158 Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
159 (if thumb then "thumb_" else "") name nregs astr
160 (if update then "_update" else "");
161 Printf.printf " [(match_parallel 0 \"%s_multiple_operation\"\n" ls;
162 begin
163 if update then begin
164 Printf.printf " [(set %s\n (plus:SI %s"
165 (destreg nregs true INOUT thumb) (destreg nregs false IN thumb);
166 Printf.printf " (const_int %d)))\n"
167 (final_offset addrmode nregs)
169 end;
170 write_pat_sets
171 (write_set_fn thumb nregs) 1
172 (initial_offset addrmode nregs)
173 (not update) nregs;
174 Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
175 (target addrmode thumb)
176 (if update then nregs + 1 else nregs);
177 Printf.printf " \"%s%%(%s%%)\\t%%%d%s, {"
178 name astr (nregs + 1) (if update then "!" else "");
179 for n = 1 to nregs; do
180 Printf.printf "%%%d%s" n (if n < nregs then ", " else "")
181 done;
182 Printf.printf "}\"\n";
183 Printf.printf " [(set_attr \"type\" \"%s%d\")" ls nregs;
184 begin if not thumb then
185 Printf.printf "\n (set_attr \"predicable\" \"yes\")";
186 end;
187 Printf.printf "])\n\n"
189 let write_ldm_pattern addrmode nregs update =
190 write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update false;
191 begin if can_thumb addrmode update false then
192 write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update true;
195 let write_stm_pattern addrmode nregs update =
196 write_pattern_1 "stm" "store" addrmode nregs write_stm_set update false;
197 begin if can_thumb addrmode update true then
198 write_pattern_1 "stm" "store" addrmode nregs write_stm_set update true;
201 let write_ldm_commutative_peephole thumb =
202 let nregs = 2 in
203 Printf.printf "(define_peephole2\n";
204 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
205 let indent = " " in
206 if thumb then begin
207 Printf.printf "\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
208 Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
209 Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
210 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
211 end else begin
212 Printf.printf "\n%s(parallel\n" indent;
213 Printf.printf "%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
214 Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
215 Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
216 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
217 Printf.printf "%s (clobber (reg:CC CC_REGNUM))])]\n" indent
218 end;
219 Printf.printf " \"(((operands[%d] == operands[0] && operands[%d] == operands[1])\n" (nregs * 2 + 2) (nregs * 2 + 3);
220 Printf.printf " || (operands[%d] == operands[0] && operands[%d] == operands[1]))\n" (nregs * 2 + 3) (nregs * 2 + 2);
221 Printf.printf " && peep2_reg_dead_p (%d, operands[0]) && peep2_reg_dead_p (%d, operands[1]))\"\n" (nregs + 1) (nregs + 1);
222 begin
223 if thumb then
224 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
225 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
226 else begin
227 Printf.printf " [(parallel\n";
228 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
229 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
230 Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
232 end;
233 Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
234 Printf.printf "})\n\n"
236 let write_ldm_peephole nregs =
237 Printf.printf "(define_peephole2\n";
238 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
239 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
240 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
242 let write_ldm_peephole_b nregs =
243 if nregs > 2 then begin
244 Printf.printf "(define_peephole2\n";
245 write_ldm_peep_set "" nregs 0 true;
246 Printf.printf "\n (parallel\n";
247 write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
248 Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
249 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
252 let write_stm_peephole nregs =
253 Printf.printf "(define_peephole2\n";
254 write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
255 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
256 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
258 let write_stm_peephole_b nregs =
259 if nregs > 2 then begin
260 Printf.printf "(define_peephole2\n";
261 write_stm_peep_set "" nregs 0 true;
262 Printf.printf "\n (parallel\n";
263 write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
264 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
265 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
268 let write_const_stm_peephole_a nregs =
269 Printf.printf "(define_peephole2\n";
270 write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
271 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
272 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
274 let write_const_stm_peephole_b nregs =
275 Printf.printf "(define_peephole2\n";
276 write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
277 Printf.printf "\n";
278 write_peep_sets (write_const_store nregs) 0 false nregs;
279 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
280 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
282 let patterns () =
283 let addrmodes = [ IA; IB; DA; DB ] in
284 let sizes = [ 4; 3; 2] in
285 List.iter
286 (fun n ->
287 List.iter
288 (fun addrmode ->
289 write_ldm_pattern addrmode n false;
290 write_ldm_pattern addrmode n true;
291 write_stm_pattern addrmode n false;
292 write_stm_pattern addrmode n true)
293 addrmodes;
294 write_ldm_peephole n;
295 write_ldm_peephole_b n;
296 write_const_stm_peephole_a n;
297 write_const_stm_peephole_b n;
298 write_stm_peephole n;)
299 sizes;
300 write_ldm_commutative_peephole false;
301 write_ldm_commutative_peephole true
303 let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
305 (* Do it. *)
307 let _ =
308 print_lines [
309 "/* ARM ldm/stm instruction patterns. This file was automatically generated";
310 " using arm-ldmstm.ml. Please do not edit manually.";
312 " Copyright (C) 2010 Free Software Foundation, Inc.";
313 " Contributed by CodeSourcery.";
315 " This file is part of GCC.";
317 " GCC is free software; you can redistribute it and/or modify it";
318 " under the terms of the GNU General Public License as published";
319 " by the Free Software Foundation; either version 3, or (at your";
320 " option) any later version.";
322 " GCC is distributed in the hope that it will be useful, but WITHOUT";
323 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
324 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
325 " License for more details.";
327 " You should have received a copy of the GNU General Public License and";
328 " a copy of the GCC Runtime Library Exception along with this program;";
329 " see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
330 " <http://www.gnu.org/licenses/>. */";
331 ""];
332 patterns ();