]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm-ldmstm.ml
Update copyright years.
[thirdparty/gcc.git] / gcc / config / arm / arm-ldmstm.ml
CommitLineData
37119410 1(* Auto-generate ARM ldm/stm patterns
8d9254fc 2 Copyright (C) 2010-2020 Free Software Foundation, Inc.
37119410
BS
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:
f0433b26 29 ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.md
37119410
BS
30*)
31
32type amode = IA | IB | DA | DB
33
34type optype = IN | OUT | INOUT
35
bae4ce0f
RR
36let rec string_of_addrmode addrmode thumb update =
37 if thumb || update
38then
37119410 39 match addrmode with
bae4ce0f
RR
40 IA -> "ia"
41 | IB -> "ib"
42 | DA -> "da"
43 | DB -> "db"
44else
45 match addrmode with
46 IA -> ""
47 | IB -> "ib"
48 | DA -> "da"
49 | DB -> "db"
37119410
BS
50
51let rec initial_offset addrmode nregs =
52 match addrmode with
53 IA -> 0
54 | IB -> 4
55 | DA -> -4 * nregs + 4
56 | DB -> -4 * nregs
57
58let rec final_offset addrmode nregs =
59 match addrmode with
60 IA -> nregs * 4
61 | IB -> nregs * 4
62 | DA -> -4 * nregs
63 | DB -> -4 * nregs
64
65let constr thumb =
66 if thumb then "l" else "rk"
67
68let inout_constr op_type =
69 match op_type with
70 OUT -> "=&"
71 | INOUT -> "+&"
72 | IN -> ""
73
74let destreg nregs first op_type thumb =
75 if not first then
76 Printf.sprintf "(match_dup %d)" (nregs + 1)
77 else
78 Printf.sprintf ("(match_operand:SI %d \"s_register_operand\" \"%s%s\")")
79 (nregs + 1) (inout_constr op_type) (constr thumb)
80
9f178d6a
CB
81let reg_predicate thumb =
82 if thumb then "low_register_operand" else "arm_hard_general_register_operand"
83
37119410
BS
84let write_ldm_set thumb nregs offset opnr first =
85 let indent = " " in
86 Printf.printf "%s" (if first then " [" else indent);
9f178d6a 87 Printf.printf "(set (match_operand:SI %d \"%s\" \"\")\n" opnr (reg_predicate thumb);
37119410
BS
88 Printf.printf "%s (mem:SI " indent;
89 begin if offset != 0 then Printf.printf "(plus:SI " end;
90 Printf.printf "%s" (destreg nregs first IN thumb);
91 begin if offset != 0 then Printf.printf "\n%s (const_int %d))" indent offset end;
92 Printf.printf "))"
93
94let write_stm_set thumb nregs offset opnr first =
95 let indent = " " in
96 Printf.printf "%s" (if first then " [" else indent);
97 Printf.printf "(set (mem:SI ";
98 begin if offset != 0 then Printf.printf "(plus:SI " end;
99 Printf.printf "%s" (destreg nregs first IN thumb);
100 begin if offset != 0 then Printf.printf " (const_int %d))" offset end;
9f178d6a 101 Printf.printf ")\n%s (match_operand:SI %d \"%s\" \"\"))" indent opnr (reg_predicate thumb)
37119410
BS
102
103let write_ldm_peep_set extra_indent nregs opnr first =
104 let indent = " " ^ extra_indent in
105 Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
106 Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
107 Printf.printf "%s (match_operand:SI %d \"memory_operand\" \"\"))" indent (nregs + opnr)
108
109let write_stm_peep_set extra_indent nregs opnr first =
110 let indent = " " ^ extra_indent in
111 Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
112 Printf.printf "(set (match_operand:SI %d \"memory_operand\" \"\")\n" (nregs + opnr);
113 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\"))" indent opnr
114
115let write_any_load optype nregs opnr first =
116 let indent = " " in
117 Printf.printf "%s" (if first then " [" else indent);
118 Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
119 Printf.printf "%s (match_operand:SI %d \"%s\" \"\"))" indent (nregs * 2 + opnr) optype
120
121let write_const_store nregs opnr first =
122 let indent = " " in
123 Printf.printf "%s(set (match_operand:SI %d \"memory_operand\" \"\")\n" indent (nregs + opnr);
124 Printf.printf "%s (match_dup %d))" indent opnr
125
126let write_const_stm_peep_set nregs opnr first =
127 write_any_load "const_int_operand" nregs opnr first;
128 Printf.printf "\n";
129 write_const_store nregs opnr false
130
131
132let rec write_pat_sets func opnr offset first n_left =
133 func offset opnr first;
134 begin
135 if n_left > 1 then begin
136 Printf.printf "\n";
137 write_pat_sets func (opnr + 1) (offset + 4) false (n_left - 1);
138 end else
139 Printf.printf "]"
140 end
141
142let rec write_peep_sets func opnr first n_left =
143 func opnr first;
144 begin
145 if n_left > 1 then begin
146 Printf.printf "\n";
147 write_peep_sets func (opnr + 1) false (n_left - 1);
148 end
149 end
150
151let can_thumb addrmode update is_store =
152 match addrmode, update, is_store with
153 (* Thumb1 mode only supports IA with update. However, for LDMIA,
154 if the address register also appears in the list of loaded
155 registers, the loaded value is stored, hence the RTL pattern
156 to describe such an insn does not have an update. We check
157 in the match_parallel predicate that the condition described
158 above is met. *)
159 IA, _, false -> true
160 | IA, true, true -> true
161 | _ -> false
162
0e26bf3d
KT
163exception InvalidAddrMode of string;;
164
37119410
BS
165let target addrmode thumb =
166 match addrmode, thumb with
167 IA, true -> "TARGET_THUMB1"
168 | IA, false -> "TARGET_32BIT"
169 | DB, false -> "TARGET_32BIT"
170 | _, false -> "TARGET_ARM"
0e26bf3d 171 | _, _ -> raise (InvalidAddrMode "ERROR: Invalid Addressing mode for Thumb1.")
37119410
BS
172
173let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
bae4ce0f 174 let astr = string_of_addrmode addrmode thumb update in
37119410
BS
175 Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
176 (if thumb then "thumb_" else "") name nregs astr
177 (if update then "_update" else "");
178 Printf.printf " [(match_parallel 0 \"%s_multiple_operation\"\n" ls;
179 begin
180 if update then begin
181 Printf.printf " [(set %s\n (plus:SI %s"
182 (destreg nregs true INOUT thumb) (destreg nregs false IN thumb);
183 Printf.printf " (const_int %d)))\n"
184 (final_offset addrmode nregs)
185 end
186 end;
187 write_pat_sets
188 (write_set_fn thumb nregs) 1
189 (initial_offset addrmode nregs)
190 (not update) nregs;
191 Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
192 (target addrmode thumb)
193 (if update then nregs + 1 else nregs);
bae4ce0f
RR
194 if thumb then
195 Printf.printf " \"%s%s\\t%%%d%s, {" name astr (nregs + 1) (if update then "!" else "")
196 else
197 Printf.printf " \"%s%s%%?\\t%%%d%s, {" name astr (nregs + 1) (if update then "!" else "");
37119410
BS
198 for n = 1 to nregs; do
199 Printf.printf "%%%d%s" n (if n < nregs then ", " else "")
200 done;
201 Printf.printf "}\"\n";
202 Printf.printf " [(set_attr \"type\" \"%s%d\")" ls nregs;
0e26bf3d 203 if not thumb then begin
37119410 204 Printf.printf "\n (set_attr \"predicable\" \"yes\")";
0e26bf3d
KT
205 if addrmode == IA || addrmode == DB then
206 Printf.printf "\n (set_attr \"predicable_short_it\" \"no\")";
37119410
BS
207 end;
208 Printf.printf "])\n\n"
209
210let write_ldm_pattern addrmode nregs update =
211 write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update false;
212 begin if can_thumb addrmode update false then
213 write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update true;
214 end
215
216let write_stm_pattern addrmode nregs update =
217 write_pattern_1 "stm" "store" addrmode nregs write_stm_set update false;
218 begin if can_thumb addrmode update true then
219 write_pattern_1 "stm" "store" addrmode nregs write_stm_set update true;
220 end
221
222let write_ldm_commutative_peephole thumb =
223 let nregs = 2 in
224 Printf.printf "(define_peephole2\n";
225 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
226 let indent = " " in
227 if thumb then begin
228 Printf.printf "\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
229 Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
230 Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
231 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
232 end else begin
233 Printf.printf "\n%s(parallel\n" indent;
234 Printf.printf "%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
235 Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
236 Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
237 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
238 Printf.printf "%s (clobber (reg:CC CC_REGNUM))])]\n" indent
239 end;
2d68f67f
GY
240 Printf.printf " \"((((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 2);
241 Printf.printf " && (REGNO (operands[%d]) == REGNO (operands[1])))\n" (nregs * 2 + 3);
242 Printf.printf " || ((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 3);
243 Printf.printf " && (REGNO (operands[%d]) == REGNO (operands[1]))))\n" (nregs * 2 + 2);
244 Printf.printf " && (peep2_regno_dead_p (%d, REGNO (operands[0]))\n" (nregs + 1);
245 Printf.printf " || (REGNO (operands[0]) == REGNO (operands[%d])))\n" (nregs * 2);
246 Printf.printf " && (peep2_regno_dead_p (%d, REGNO (operands[1]))\n" (nregs + 1);
247 Printf.printf " || (REGNO (operands[1]) == REGNO (operands[%d]))))\"\n" (nregs * 2);
37119410
BS
248 begin
249 if thumb then
250 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
251 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
252 else begin
253 Printf.printf " [(parallel\n";
254 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
255 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
256 Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
257 end
258 end;
259 Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
260 Printf.printf "})\n\n"
261
262let write_ldm_peephole nregs =
263 Printf.printf "(define_peephole2\n";
264 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
265 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
266 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
267
268let write_ldm_peephole_b nregs =
269 if nregs > 2 then begin
270 Printf.printf "(define_peephole2\n";
271 write_ldm_peep_set "" nregs 0 true;
272 Printf.printf "\n (parallel\n";
273 write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
274 Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
275 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
276 end
277
278let write_stm_peephole nregs =
279 Printf.printf "(define_peephole2\n";
280 write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
281 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
282 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
283
284let write_stm_peephole_b nregs =
285 if nregs > 2 then begin
286 Printf.printf "(define_peephole2\n";
287 write_stm_peep_set "" nregs 0 true;
288 Printf.printf "\n (parallel\n";
289 write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
290 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
291 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
292 end
293
294let write_const_stm_peephole_a nregs =
295 Printf.printf "(define_peephole2\n";
296 write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
297 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
298 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
299
300let write_const_stm_peephole_b nregs =
301 Printf.printf "(define_peephole2\n";
302 write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
303 Printf.printf "\n";
304 write_peep_sets (write_const_store nregs) 0 false nregs;
305 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
306 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
307
308let patterns () =
309 let addrmodes = [ IA; IB; DA; DB ] in
310 let sizes = [ 4; 3; 2] in
311 List.iter
312 (fun n ->
313 List.iter
314 (fun addrmode ->
315 write_ldm_pattern addrmode n false;
316 write_ldm_pattern addrmode n true;
317 write_stm_pattern addrmode n false;
318 write_stm_pattern addrmode n true)
319 addrmodes;
320 write_ldm_peephole n;
321 write_ldm_peephole_b n;
322 write_const_stm_peephole_a n;
323 write_const_stm_peephole_b n;
324 write_stm_peephole n;)
325 sizes;
326 write_ldm_commutative_peephole false;
327 write_ldm_commutative_peephole true
328
329let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
330
331(* Do it. *)
332
333let _ =
334 print_lines [
335"/* ARM ldm/stm instruction patterns. This file was automatically generated";
336" using arm-ldmstm.ml. Please do not edit manually.";
337"";
8d9254fc 338" Copyright (C) 2010-2020 Free Software Foundation, Inc.";
37119410
BS
339" Contributed by CodeSourcery.";
340"";
341" This file is part of GCC.";
342"";
343" GCC is free software; you can redistribute it and/or modify it";
344" under the terms of the GNU General Public License as published";
345" by the Free Software Foundation; either version 3, or (at your";
346" option) any later version.";
347"";
348" GCC is distributed in the hope that it will be useful, but WITHOUT";
349" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
350" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
351" License for more details.";
352"";
353" You should have received a copy of the GNU General Public License and";
354" a copy of the GCC Runtime Library Exception along with this program;";
355" see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
356" <http://www.gnu.org/licenses/>. */";
357""];
358 patterns ();