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 write_ldm_set thumb nregs offset opnr first =
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;
80 let write_stm_set thumb nregs offset opnr first =
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 =
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 =
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;
115 write_const_store nregs opnr false
118 let rec write_pat_sets func opnr offset first n_left =
119 func offset opnr first;
121 if n_left > 1 then begin
123 write_pat_sets func (opnr + 1) (offset + 4) false (n_left - 1);
128 let rec write_peep_sets func opnr first n_left =
131 if n_left > 1 then begin
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
146 | IA, true, true -> true
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;
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)
171 (write_set_fn thumb nregs) 1
172 (initial_offset addrmode 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 "")
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\")";
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 =
203 Printf.printf "(define_peephole2\n";
204 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
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)
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
219 Printf.printf " \"((((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 2);
220 Printf.printf " && (REGNO (operands[%d]) == REGNO (operands[1])))\n" (nregs * 2 + 3);
221 Printf.printf " || ((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 3);
222 Printf.printf " && (REGNO (operands[%d]) == REGNO (operands[1]))))\n" (nregs * 2 + 2);
223 Printf.printf " && (peep2_regno_dead_p (%d, REGNO (operands[0]))\n" (nregs + 1);
224 Printf.printf " || (REGNO (operands[0]) == REGNO (operands[%d])))\n" (nregs * 2);
225 Printf.printf " && (peep2_regno_dead_p (%d, REGNO (operands[1]))\n" (nregs + 1);
226 Printf.printf " || (REGNO (operands[1]) == REGNO (operands[%d]))))\"\n" (nregs * 2);
229 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
230 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
232 Printf.printf " [(parallel\n";
233 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
234 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
235 Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
238 Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
239 Printf.printf "})\n\n"
241 let write_ldm_peephole nregs =
242 Printf.printf "(define_peephole2\n";
243 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
244 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
245 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
247 let write_ldm_peephole_b nregs =
248 if nregs > 2 then begin
249 Printf.printf "(define_peephole2\n";
250 write_ldm_peep_set "" nregs 0 true;
251 Printf.printf "\n (parallel\n";
252 write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
253 Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
254 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
257 let write_stm_peephole nregs =
258 Printf.printf "(define_peephole2\n";
259 write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
260 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
261 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
263 let write_stm_peephole_b nregs =
264 if nregs > 2 then begin
265 Printf.printf "(define_peephole2\n";
266 write_stm_peep_set "" nregs 0 true;
267 Printf.printf "\n (parallel\n";
268 write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
269 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
270 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
273 let write_const_stm_peephole_a nregs =
274 Printf.printf "(define_peephole2\n";
275 write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
276 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
277 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
279 let write_const_stm_peephole_b nregs =
280 Printf.printf "(define_peephole2\n";
281 write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
283 write_peep_sets (write_const_store nregs) 0 false 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
288 let addrmodes = [ IA; IB; DA; DB ] in
289 let sizes = [ 4; 3; 2] in
294 write_ldm_pattern addrmode n false;
295 write_ldm_pattern addrmode n true;
296 write_stm_pattern addrmode n false;
297 write_stm_pattern addrmode n true)
299 write_ldm_peephole n;
300 write_ldm_peephole_b n;
301 write_const_stm_peephole_a n;
302 write_const_stm_peephole_b n;
303 write_stm_peephole n;)
305 write_ldm_commutative_peephole false;
306 write_ldm_commutative_peephole true
308 let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
314 "/* ARM ldm/stm instruction patterns. This file was automatically generated";
315 " using arm-ldmstm.ml. Please do not edit manually.";
317 " Copyright (C) 2010-2013 Free Software Foundation, Inc.";
318 " Contributed by CodeSourcery.";
320 " This file is part of GCC.";
322 " GCC is free software; you can redistribute it and/or modify it";
323 " under the terms of the GNU General Public License as published";
324 " by the Free Software Foundation; either version 3, or (at your";
325 " option) any later version.";
327 " GCC is distributed in the hope that it will be useful, but WITHOUT";
328 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
329 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
330 " License for more details.";
332 " You should have received a copy of the GNU General Public License and";
333 " a copy of the GCC Runtime Library Exception along with this program;";
334 " see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
335 " <http://www.gnu.org/licenses/>. */";