]>
Commit | Line | Data |
---|---|---|
37119410 BS |
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 (); |