1 /* Auxiliary functions for expand movmem, setmem, cmpmem, load_multiple 2 and store_multiple pattern of Andes NDS32 cpu for GNU compiler 3 Copyright (C) 2012-2015 Free Software Foundation, Inc. 4 Contributed by Andes Technology Corporation. 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify it 9 under the terms of the GNU General Public License as published 10 by the Free Software Foundation; either version 3, or (at your 11 option) any later version. 12 13 GCC is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 16 License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GCC; see the file COPYING3. If not see 20 <http://www.gnu.org/licenses/>. */ 21 22 /* ------------------------------------------------------------------------ */ 23 24 #include "config.h" 25 #include "system.h" 26 #include "coretypes.h" 27 #include "tm.h" 28 #include "hash-set.h" 29 #include "machmode.h" 30 #include "vec.h" 31 #include "double-int.h" 32 #include "input.h" 33 #include "alias.h" 34 #include "symtab.h" 35 #include "wide-int.h" 36 #include "inchash.h" 37 #include "tree.h" 38 #include "stor-layout.h" 39 #include "varasm.h" 40 #include "calls.h" 41 #include "rtl.h" 42 #include "regs.h" 43 #include "hard-reg-set.h" 44 #include "insn-config.h" /* Required by recog.h. */ 45 #include "conditions.h" 46 #include "output.h" 47 #include "insn-attr.h" /* For DFA state_t. */ 48 #include "insn-codes.h" /* For CODE_FOR_xxx. */ 49 #include "reload.h" /* For push_reload(). */ 50 #include "flags.h" 51 #include "function.h" 52 #include "hashtab.h" 53 #include "statistics.h" 54 #include "real.h" 55 #include "fixed-value.h" 56 #include "insn-config.h" 57 #include "expmed.h" 58 #include "dojump.h" 59 #include "explow.h" 60 #include "emit-rtl.h" 61 #include "stmt.h" 62 #include "expr.h" 63 #include "recog.h" 64 #include "diagnostic-core.h" 65 #include "dominance.h" 66 #include "cfg.h" 67 #include "cfgrtl.h" 68 #include "cfganal.h" 69 #include "lcm.h" 70 #include "cfgbuild.h" 71 #include "cfgcleanup.h" 72 #include "predict.h" 73 #include "basic-block.h" 74 #include "df.h" 75 #include "tm_p.h" 76 #include "tm-constrs.h" 77 #include "optabs.h" /* For GEN_FCN. */ 78 #include "target.h" 79 #include "target-def.h" 80 #include "langhooks.h" /* For add_builtin_function(). */ 81 #include "ggc.h" 82 #include "builtins.h" 83 84 /* ------------------------------------------------------------------------ */ 85 86 /* Functions to expand load_multiple and store_multiple. 87 They are auxiliary extern functions to help create rtx template. 88 Check nds32-multiple.md file for the patterns. */ 89 rtx 90 nds32_expand_load_multiple (int base_regno, int count, 91 rtx base_addr, rtx basemem) 92 { 93 int par_index; 94 int offset; 95 rtx result; 96 rtx new_addr, mem, reg; 97 98 /* Create the pattern that is presented in nds32-multiple.md. */ 99 100 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); 101 102 for (par_index = 0; par_index < count; par_index++) 103 { 104 offset = par_index * 4; 105 /* 4-byte for loading data to each register. */ 106 new_addr = plus_constant (Pmode, base_addr, offset); 107 mem = adjust_automodify_address_nv (basemem, SImode, 108 new_addr, offset); 109 reg = gen_rtx_REG (SImode, base_regno + par_index); 110 111 XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, reg, mem); 112 } 113 114 return result; 115 } 116 117 rtx 118 nds32_expand_store_multiple (int base_regno, int count, 119 rtx base_addr, rtx basemem) 120 { 121 int par_index; 122 int offset; 123 rtx result; 124 rtx new_addr, mem, reg; 125 126 /* Create the pattern that is presented in nds32-multiple.md. */ 127 128 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); 129 130 for (par_index = 0; par_index < count; par_index++) 131 { 132 offset = par_index * 4; 133 /* 4-byte for storing data to memory. */ 134 new_addr = plus_constant (Pmode, base_addr, offset); 135 mem = adjust_automodify_address_nv (basemem, SImode, 136 new_addr, offset); 137 reg = gen_rtx_REG (SImode, base_regno + par_index); 138 139 XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, mem, reg); 140 } 141 142 return result; 143 } 144 145 /* Function to move block memory content by 146 using load_multiple and store_multiple. 147 This is auxiliary extern function to help create rtx template. 148 Check nds32-multiple.md file for the patterns. */ 149 int 150 nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment) 151 { 152 HOST_WIDE_INT in_words, out_words; 153 rtx dst_base_reg, src_base_reg; 154 int maximum_bytes; 155 156 /* Because reduced-set regsiters has few registers 157 (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' 158 cannot be used for register allocation), 159 using 8 registers (32 bytes) for moving memory block 160 may easily consume all of them. 161 It makes register allocation/spilling hard to work. 162 So we only allow maximum=4 registers (16 bytes) for 163 moving memory block under reduced-set registers. */ 164 if (TARGET_REDUCED_REGS) 165 maximum_bytes = 16; 166 else 167 maximum_bytes = 32; 168 169 /* 1. Total_bytes is integer for sure. 170 2. Alignment is integer for sure. 171 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes. 172 4. Requires (n * 4) block size. 173 5. Requires 4-byte alignment. */ 174 if (GET_CODE (total_bytes) != CONST_INT 175 || GET_CODE (alignment) != CONST_INT 176 || INTVAL (total_bytes) > maximum_bytes 177 || INTVAL (total_bytes) & 3 178 || INTVAL (alignment) & 3) 179 return 0; 180 181 dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0)); 182 src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0)); 183 184 out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD; 185 186 emit_insn (nds32_expand_load_multiple (0, in_words, src_base_reg, srcmem)); 187 emit_insn (nds32_expand_store_multiple (0, out_words, dst_base_reg, dstmem)); 188 189 /* Successfully create patterns, return 1. */ 190 return 1; 191 } 192 193 /* ------------------------------------------------------------------------ */ 194