1 1.1 mrg (* Auto-generate Nios II R2 CDX ldwm/stwm/push.n/pop.n patterns 2 1.7 mrg Copyright (C) 2014-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Mentor Graphics. 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 a Standard ML program. There are multiple Standard ML 22 1.1 mrg implementations widely available. We recommend the MLton optimizing 23 1.1 mrg SML compiler, due to its ease of creating a standalone executable. 24 1.1 mrg 25 1.1 mrg http://www.mlton.org/ 26 1.1 mrg 27 1.1 mrg Or from your favourite OS's friendly packaging system. Tested with 28 1.1 mrg MLton Release 20130715, though other versions will probably work too. 29 1.1 mrg 30 1.1 mrg Run with: 31 1.1 mrg mlton -output a.out /path/to/gcc/config/nios2/nios2-ldstwm.sml 32 1.1 mrg ./a.out >/path/to/gcc/config/nios2/ldstwm.md 33 1.1 mrg *) 34 1.1 mrg 35 1.1 mrg datatype ld_st = ld | st; 36 1.1 mrg datatype push_pop = push | pop; 37 1.1 mrg datatype inc_dec = inc | dec; 38 1.1 mrg 39 1.1 mrg fun for ls f = map f ls; 40 1.1 mrg fun conds cond str = if cond then str else ""; 41 1.1 mrg fun ints n = if n>=0 then (Int.toString n) else ("-" ^ (Int.toString (~n))); 42 1.1 mrg 43 1.1 mrg fun pushpop_pattern pptype n fp = 44 1.1 mrg let 45 1.1 mrg val sp_reg = "(reg:SI SP_REGNO)"; 46 1.1 mrg val ra_reg = "(reg:SI RA_REGNO)"; 47 1.1 mrg val fp_reg = "(reg:SI FP_REGNO)"; 48 1.1 mrg 49 1.1 mrg fun sets lhs rhs = "(set " ^ lhs ^ 50 1.1 mrg (if pptype=push then " " 51 1.1 mrg else " ") ^ rhs ^ ")"; 52 1.1 mrg val sp_adj = 53 1.1 mrg "(set " ^ sp_reg ^ "\n " ^ 54 1.1 mrg "(plus:SI " ^ sp_reg ^ 55 1.1 mrg " (match_operand 1 \"const_int_operand\" \"\")))"; 56 1.1 mrg 57 1.1 mrg fun reg i regi = "(reg:SI " ^ (ints regi) ^ ")"; 58 1.1 mrg fun mem i opndi = 59 1.1 mrg if pptype=push then 60 1.1 mrg "(mem:SI (plus:SI (reg:SI SP_REGNO) (const_int " ^ (ints (~4*i)) ^ ")))" 61 1.1 mrg else 62 1.1 mrg "(match_operand:SI " ^ 63 1.1 mrg (ints opndi) ^ " \"stack_memory_operand\" \"\")"; 64 1.1 mrg 65 1.1 mrg val start = 1 + (if fp then 2 else 1); 66 1.1 mrg val lim = n + (if fp then 2 else 1); 67 1.1 mrg fun set_elt i regi opndi = 68 1.1 mrg if pptype=push then (sets (mem i opndi) (reg i regi)) 69 1.1 mrg else (sets (reg i regi) (mem i opndi)); 70 1.1 mrg fun get_elt_list (i, regi, opndi) = 71 1.1 mrg if i > lim then [] 72 1.1 mrg else (set_elt i regi opndi) :: get_elt_list (i+1, regi-1, opndi+1); 73 1.1 mrg 74 1.1 mrg val set_elements = get_elt_list (start, 16+n-1, start+1); 75 1.1 mrg 76 1.1 mrg val ra_set = if pptype=push then sets (mem 1 2) ra_reg 77 1.1 mrg else sets ra_reg (mem 1 2); 78 1.1 mrg val fp_set = (conds fp (if pptype=push then sets (mem 2 3) fp_reg 79 1.1 mrg else sets fp_reg (mem 2 3))); 80 1.1 mrg val ret = (conds (pptype=pop) "(return)"); 81 1.1 mrg val element_list = 82 1.1 mrg List.filter (fn x => x<>"") 83 1.1 mrg ([ret, sp_adj, ra_set, fp_set] @ set_elements); 84 1.1 mrg 85 1.1 mrg fun reg_index i = 16 + n - i; 86 1.1 mrg fun pop_opnds 0 spl = (conds fp ("fp" ^ spl)) ^ "ra" 87 1.1 mrg | pop_opnds n spl = "r" ^ (ints (reg_index n)) ^ spl ^ (pop_opnds (n-1) spl); 88 1.1 mrg fun push_opnds 0 spl = "ra" ^ (conds fp (spl ^ "fp")) 89 1.1 mrg | push_opnds n spl = (push_opnds (n-1) spl) ^ spl ^ "r" ^ (ints (reg_index n)); 90 1.1 mrg 91 1.1 mrg val spadj_opnd = if pptype=push then 2 else (start+n); 92 1.1 mrg val spadj = ints spadj_opnd; 93 1.1 mrg val regsave_num = n + (if fp then 2 else 1); 94 1.1 mrg 95 1.1 mrg val ppname = if pptype=push then "push" else "pop"; 96 1.1 mrg val name = if pptype=push then "push" ^ "_" ^ (push_opnds n "_") 97 1.1 mrg else "pop" ^ "_" ^ (pop_opnds n "_"); 98 1.1 mrg in 99 1.1 mrg "(define_insn \"*cdx_" ^ name ^ "\"\n" ^ 100 1.1 mrg " [(match_parallel 0 \"" ^ 101 1.1 mrg (conds (pptype=pop) "pop_operation") ^ "\"\n" ^ 102 1.1 mrg " [" ^ (String.concatWith ("\n ") element_list) ^ "])]\n" ^ 103 1.1 mrg " \"TARGET_HAS_CDX && XVECLEN (operands[0], 0) == " ^ 104 1.1 mrg (ints (length element_list)) ^ 105 1.1 mrg (conds (pptype=push) 106 1.1 mrg ("\n && (-INTVAL (operands[1]) & 3) == 0\n" ^ 107 1.1 mrg " && (-INTVAL (operands[1]) - " ^ 108 1.1 mrg (ints (4*regsave_num)) ^ ") <= 60")) ^ 109 1.1 mrg "\"\n" ^ 110 1.1 mrg (if pptype=pop then 111 1.1 mrg "{\n" ^ 112 1.1 mrg " rtx x = XEXP (operands[" ^ spadj ^ "], 0);\n" ^ 113 1.1 mrg " operands[" ^ spadj ^ "] = REG_P (x) ? const0_rtx : XEXP (x, 1);\n" ^ 114 1.1 mrg " return \"pop.n\\\\t{" ^ (pop_opnds n ", ") ^ "}, %" ^ spadj ^ "\";\n" ^ 115 1.1 mrg "}\n" 116 1.1 mrg else 117 1.1 mrg "{\n" ^ 118 1.1 mrg " operands[" ^ spadj ^ "] = " ^ 119 1.1 mrg "GEN_INT (-INTVAL (operands[1]) - " ^ (ints (4*regsave_num)) ^ ");\n" ^ 120 1.1 mrg " return \"push.n\\\\t{" ^ (push_opnds n ", ") ^ "}, %" ^ spadj ^ "\";\n" ^ 121 1.1 mrg "}\n") ^ 122 1.1 mrg " [(set_attr \"type\" \"" ^ ppname ^ "\")])\n\n" 123 1.1 mrg end; 124 1.1 mrg 125 1.1 mrg fun ldstwm_pattern ldst n id wb pc = 126 1.1 mrg let 127 1.1 mrg val ldstwm = (if ldst=ld then "ldwm" else "stwm"); 128 1.1 mrg val name = "*cdx_" ^ ldstwm ^ (Int.toString n) ^ 129 1.1 mrg (if id=inc then "_inc" else "_dec") ^ 130 1.1 mrg (conds wb "_wb") ^ (conds pc "_ret"); 131 1.1 mrg val base_reg_referenced_p = ref false; 132 1.1 mrg val base_regno = ints (n+1); 133 1.1 mrg fun plus_addr base offset = 134 1.1 mrg "(plus:SI " ^ base ^ " (const_int " ^ (ints offset) ^ "))"; 135 1.1 mrg fun base_reg () = 136 1.1 mrg if !base_reg_referenced_p then 137 1.1 mrg "(match_dup " ^ base_regno ^ ")" 138 1.1 mrg else (base_reg_referenced_p := true; 139 1.1 mrg "(match_operand:SI " ^ base_regno ^ 140 1.1 mrg " \"register_operand\" \"" ^ (conds wb "+&") ^ "r\")"); 141 1.1 mrg fun reg i = "(match_operand:SI " ^ (ints i) ^ 142 1.1 mrg " \"nios2_hard_register_operand\" \"" ^ 143 1.1 mrg (conds (ldst=ld) "") ^ "\")"; 144 1.1 mrg 145 1.1 mrg fun addr 1 = if id=inc then base_reg () 146 1.1 mrg else plus_addr (base_reg ()) (~4) 147 1.1 mrg | addr i = let val offset = if id=inc then (i-1)*4 else (~i*4) 148 1.1 mrg in plus_addr (base_reg ()) offset end; 149 1.1 mrg 150 1.1 mrg fun mem i = "(mem:SI " ^ (addr i) ^ ")"; 151 1.1 mrg fun lhs i = if ldst=ld then reg i else mem i; 152 1.1 mrg fun rhs i = if ldst=st then reg i else mem i; 153 1.1 mrg fun sets lhs rhs = "(set " ^ lhs ^ "\n " ^ rhs ^ ")"; 154 1.1 mrg fun set_elements i = 155 1.1 mrg if i > n then [] 156 1.1 mrg else (sets (lhs i) (rhs i)) :: (set_elements (i+1)); 157 1.1 mrg 158 1.1 mrg fun opnds 1 = "%1" 159 1.1 mrg | opnds n = opnds(n-1) ^ ", %" ^ (Int.toString n); 160 1.1 mrg 161 1.1 mrg val asm_template = ldstwm ^ "\\\\t{" ^ (opnds n) ^ "}" ^ 162 1.1 mrg (if id=inc 163 1.1 mrg then ", (%" ^ base_regno ^ ")++" 164 1.1 mrg else ", --(%" ^ base_regno ^ ")") ^ 165 1.1 mrg (conds wb ", writeback") ^ 166 1.1 mrg (conds pc ", ret"); 167 1.1 mrg val wbtmp = 168 1.1 mrg if wb then 169 1.1 mrg (sets (base_reg ()) 170 1.1 mrg (plus_addr (base_reg ()) 171 1.1 mrg ((if id=inc then n else ~n)*4))) 172 1.1 mrg else ""; 173 1.1 mrg val pctmp = conds pc "(return)"; 174 1.1 mrg val set_list = List.filter (fn x => x<>"") 175 1.1 mrg ([pctmp, wbtmp] @ (set_elements 1)); 176 1.1 mrg in 177 1.1 mrg if ldst=st andalso pc then "" 178 1.1 mrg else 179 1.1 mrg "(define_insn \"" ^ name ^ "\"\n" ^ 180 1.1 mrg " [(match_parallel 0 \"" ^ ldstwm ^ "_operation\"\n" ^ 181 1.1 mrg " [" ^ (String.concatWith ("\n ") set_list) ^ "])]\n" ^ 182 1.1 mrg " \"TARGET_HAS_CDX && XVECLEN (operands[0], 0) == " ^ 183 1.1 mrg (ints (length set_list)) ^ "\"\n" ^ 184 1.1 mrg " \"" ^ asm_template ^ "\"\n" ^ 185 1.1 mrg " [(set_attr \"type\" \"" ^ ldstwm ^ "\")])\n\n" 186 1.1 mrg end; 187 1.1 mrg 188 1.1 mrg fun peephole_pattern ldst n scratch_p = 189 1.1 mrg let 190 1.1 mrg fun sets lhs rhs = "(set " ^ lhs ^ "\n " ^ rhs ^ ")"; 191 1.1 mrg fun single_set i indent = 192 1.1 mrg let val reg = "(match_operand:SI " ^ (ints i) ^ 193 1.1 mrg " \"register_operand\" \"\")"; 194 1.1 mrg val mem = "(match_operand:SI " ^ (ints (i+n)) ^ 195 1.1 mrg " \"memory_operand\" \"\")"; 196 1.1 mrg in 197 1.1 mrg if ldst=ld then sets reg mem 198 1.1 mrg else sets mem reg 199 1.1 mrg end; 200 1.1 mrg 201 1.1 mrg fun single_sets i = 202 1.1 mrg if i=n then [] 203 1.1 mrg else (single_set i " ") :: (single_sets (i+1)); 204 1.1 mrg 205 1.1 mrg val scratch = ints (2*n); 206 1.1 mrg val peephole_elements = 207 1.1 mrg let val tmp = single_sets 0 in 208 1.1 mrg if scratch_p 209 1.1 mrg then (["(match_scratch:SI " ^ scratch ^ " \"r\")"] @ 210 1.1 mrg tmp @ 211 1.1 mrg ["(match_dup " ^ scratch ^ ")"]) 212 1.1 mrg else tmp 213 1.1 mrg end; 214 1.1 mrg in 215 1.1 mrg "(define_peephole2\n" ^ 216 1.1 mrg " [" ^ (String.concatWith ("\n ") peephole_elements) ^ "]\n" ^ 217 1.1 mrg " \"TARGET_HAS_CDX\"\n" ^ 218 1.1 mrg " [(const_int 0)]\n" ^ 219 1.1 mrg "{\n" ^ 220 1.1 mrg " if (gen_ldstwm_peep (" ^ 221 1.1 mrg (if ldst=st then "false" else "true") ^ ", " ^ (ints n) ^ ", " ^ 222 1.1 mrg (if scratch_p then ("operands[" ^ scratch ^ "]") else "NULL_RTX") ^ 223 1.1 mrg ", operands))\n" ^ 224 1.1 mrg " DONE;\n" ^ 225 1.1 mrg " else\n" ^ 226 1.1 mrg " FAIL;\n" ^ 227 1.1 mrg "})\n\n" 228 1.1 mrg end; 229 1.1 mrg 230 1.1 mrg 231 1.1 mrg print 232 1.1 mrg ("/* Nios II R2 CDX ldwm/stwm/push.h/pop.n instruction patterns.\n" ^ 233 1.1 mrg " This file was automatically generated using nios2-ldstwm.sml.\n" ^ 234 1.1 mrg " Please do not edit manually.\n" ^ 235 1.1 mrg "\n" ^ 236 1.7 mrg " Copyright (C) 2014-2022 Free Software Foundation, Inc.\n" ^ 237 1.1 mrg " Contributed by Mentor Graphics.\n" ^ 238 1.1 mrg "\n" ^ 239 1.1 mrg " This file is part of GCC.\n" ^ 240 1.1 mrg "\n" ^ 241 1.1 mrg " GCC is free software; you can redistribute it and/or modify it\n" ^ 242 1.1 mrg " under the terms of the GNU General Public License as published\n" ^ 243 1.1 mrg " by the Free Software Foundation; either version 3, or (at your\n" ^ 244 1.1 mrg " option) any later version.\n" ^ 245 1.1 mrg "\n" ^ 246 1.1 mrg " GCC is distributed in the hope that it will be useful, but WITHOUT\n" ^ 247 1.1 mrg " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n" ^ 248 1.1 mrg " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n" ^ 249 1.1 mrg " License for more details.\n" ^ 250 1.1 mrg "\n" ^ 251 1.1 mrg " You should have received a copy of the GNU General Public License and\n" ^ 252 1.1 mrg " a copy of the GCC Runtime Library Exception along with this program;\n" ^ 253 1.1 mrg " see the files COPYING3 and COPYING.RUNTIME respectively. If not, see\n" ^ 254 1.1 mrg " <http://www.gnu.org/licenses/>. */\n\n"); 255 1.1 mrg 256 1.1 mrg fun seq a b = if a=b then [b] 257 1.1 mrg else a :: (seq (if a<b then a+1 else a-1) b); 258 1.1 mrg 259 1.1 mrg (* push/pop patterns *) 260 1.1 mrg for (seq 0 8) (fn n => 261 1.1 mrg for [push, pop] (fn p => 262 1.1 mrg for [true, false] (fn fp => 263 1.1 mrg print (pushpop_pattern p n fp)))); 264 1.1 mrg 265 1.1 mrg (* ldwm/stwm patterns *) 266 1.1 mrg for [ld, st] (fn l => 267 1.1 mrg for (seq 1 12) (fn n => 268 1.1 mrg for [inc, dec] (fn id => 269 1.1 mrg for [true, false] (fn wb => 270 1.1 mrg for [true, false] (fn pc => 271 1.1 mrg print (ldstwm_pattern l n id wb pc)))))); 272 1.1 mrg 273 1.1 mrg (* peephole patterns *) 274 1.1 mrg for [ld, st] (fn l => 275 1.1 mrg for (seq 12 2) (fn n => 276 1.1 mrg print (peephole_pattern l n true))); 277 1.1 mrg 278