OSDN Git Service

PR target/40457
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm-ldmstm.ml
1 (* Auto-generate ARM ldm/stm patterns
2    Copyright (C) 2010 Free Software Foundation, Inc.
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:
29      ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.ml
30 *)
31
32 type amode = IA | IB | DA | DB
33
34 type optype = IN | OUT | INOUT
35
36 let rec string_of_addrmode addrmode =
37   match addrmode with
38     IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
39
40 let 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
47 let 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
54 let constr thumb =
55   if thumb then "l" else "rk"
56
57 let inout_constr op_type =
58   match op_type with
59   OUT -> "=&"
60   | INOUT -> "+&"
61   | IN -> ""
62
63 let 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
70 let 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
80 let 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
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)
94
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
100
101 let 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
107 let 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
112 let 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   
118 let 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
128 let 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     
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
144        above is met.  *)
145     IA, _, false -> true
146   | IA, true, true -> true
147   | _ -> false
148
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"
155
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;
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
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;
193   end
194
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;
199   end
200
201 let 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;
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);
222   begin
223     if thumb then
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)
226     else begin
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"
231     end
232   end;
233   Printf.printf "{\n  if (!gen_ldm_seq (operands, %d, true))\n    FAIL;\n" nregs;
234   Printf.printf "})\n\n"
235
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
241
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
250   end
251
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
257
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
266   end
267
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
273
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;
277   Printf.printf "\n";
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
281
282 let patterns () =
283   let addrmodes = [ IA; IB; DA; DB ]  in
284   let sizes = [ 4; 3; 2] in
285   List.iter
286     (fun n ->
287       List.iter
288         (fun addrmode ->
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)
293         addrmodes;
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;)
299     sizes;
300   write_ldm_commutative_peephole false;
301   write_ldm_commutative_peephole true
302
303 let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
304
305 (* Do it.  *)
306
307 let _ = 
308   print_lines [
309 "/* ARM ldm/stm instruction patterns.  This file was automatically generated";
310 "   using arm-ldmstm.ml.  Please do not edit manually.";
311 "";
312 "   Copyright (C) 2010 Free Software Foundation, Inc.";
313 "   Contributed by CodeSourcery.";
314 "";
315 "   This file is part of GCC.";
316 "";
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.";
321 "";
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.";
326 "";
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/>.  */";
331 ""];
332   patterns ();