]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm-ldmstm.ml
Update Copyright years for files modified in 2011 and/or 2012.
[thirdparty/gcc.git] / gcc / config / arm / arm-ldmstm.ml
CommitLineData
320ea44d 1(* Auto-generate ARM ldm/stm patterns
71e45bc2 2 Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc.
320ea44d 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:
84d198a3 29 ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.md
320ea44d 30*)
31
32type amode = IA | IB | DA | DB
33
34type optype = IN | OUT | INOUT
35
36let rec string_of_addrmode addrmode =
37 match addrmode with
38 IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
39
40let 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
47let 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
54let constr thumb =
55 if thumb then "l" else "rk"
56
57let inout_constr op_type =
58 match op_type with
59 OUT -> "=&"
60 | INOUT -> "+&"
61 | IN -> ""
62
63let 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
70let 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
80let 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
89let 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
95let 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
101let 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
107let 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
112let 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
118let 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
128let 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
137let 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
149let 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"
155
156let 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)
168 end
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"
188
189let 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;
193 end
194
195let 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;
199 end
200
201let 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;
9811ae10 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);
320ea44d 227 begin
228 if thumb then
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)
231 else begin
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"
236 end
237 end;
238 Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
239 Printf.printf "})\n\n"
240
241let 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
246
247let 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
255 end
256
257let 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
262
263let 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
271 end
272
273let 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
278
279let 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;
282 Printf.printf "\n";
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
286
287let patterns () =
288 let addrmodes = [ IA; IB; DA; DB ] in
289 let sizes = [ 4; 3; 2] in
290 List.iter
291 (fun n ->
292 List.iter
293 (fun addrmode ->
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)
298 addrmodes;
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;)
304 sizes;
305 write_ldm_commutative_peephole false;
306 write_ldm_commutative_peephole true
307
308let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
309
310(* Do it. *)
311
312let _ =
313 print_lines [
314"/* ARM ldm/stm instruction patterns. This file was automatically generated";
315" using arm-ldmstm.ml. Please do not edit manually.";
316"";
71e45bc2 317" Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc.";
320ea44d 318" Contributed by CodeSourcery.";
319"";
320" This file is part of GCC.";
321"";
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.";
326"";
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.";
331"";
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/>. */";
336""];
337 patterns ();