1(* Auto-generate ARM ldm/stm patterns 2 Copyright (C) 2010-2020 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 thumb update = 37 if thumb || update 38then 39 match addrmode with 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" 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 81let reg_predicate thumb = 82 if thumb then "low_register_operand" else "arm_hard_general_register_operand" 83 84let write_ldm_set thumb nregs offset opnr first = 85 let indent = " " in 86 Printf.printf "%s" (if first then " [" else indent); 87 Printf.printf "(set (match_operand:SI %d \"%s\" \"\")\n" opnr (reg_predicate thumb); 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; 101 Printf.printf ")\n%s (match_operand:SI %d \"%s\" \"\"))" indent opnr (reg_predicate thumb) 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 163exception InvalidAddrMode of string;; 164 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" 171 | _, _ -> raise (InvalidAddrMode "ERROR: Invalid Addressing mode for Thumb1.") 172 173let write_pattern_1 name ls addrmode nregs write_set_fn update thumb = 174 let astr = string_of_addrmode addrmode thumb update in 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); 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 ""); 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; 203 if not thumb then begin 204 Printf.printf "\n (set_attr \"predicable\" \"yes\")"; 205 if addrmode == IA || addrmode == DB then 206 Printf.printf "\n (set_attr \"predicable_short_it\" \"no\")"; 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; 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); 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""; 338" Copyright (C) 2010-2020 Free Software Foundation, Inc."; 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 (); 359