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
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.ml
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 " \"(((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);
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)
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"
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;
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
283 let addrmodes = [ IA; IB; DA; DB ] in
284 let sizes = [ 4; 3; 2] in
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)
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;)
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)
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/>. */";