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