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