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_general_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_general_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 exception InvalidAddrMode of string;;
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.")
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;
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)
174 (write_set_fn thumb nregs) 1
175 (initial_offset addrmode 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 "")
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\")";
192 Printf.printf "])\n\n"
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;
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;
206 let write_ldm_commutative_peephole thumb =
208 Printf.printf "(define_peephole2\n";
209 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
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)
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
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);
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)
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"
243 Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
244 Printf.printf "})\n\n"
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
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
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
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
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
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;
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
293 let addrmodes = [ IA; IB; DA; DB ] in
294 let sizes = [ 4; 3; 2] in
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)
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;)
310 write_ldm_commutative_peephole false;
311 write_ldm_commutative_peephole true
313 let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
319 "/* ARM ldm/stm instruction patterns. This file was automatically generated";
320 " using arm-ldmstm.ml. Please do not edit manually.";
322 " Copyright (C) 2010-2013 Free Software Foundation, Inc.";
323 " Contributed by CodeSourcery.";
325 " This file is part of GCC.";
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.";
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.";
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/>. */";