gcc/
[official-gcc.git] / gcc / config / nds32 / nds32-memory-manipulation.c
blob9dc52f20de0f6e1cc857ccf446fae9762ce08649
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.
6 This file is part of GCC.
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.
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.
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/>. */
22 /* ------------------------------------------------------------------------ */
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"
84 /* ------------------------------------------------------------------------ */
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)
93 int par_index;
94 int offset;
95 rtx result;
96 rtx new_addr, mem, reg;
98 /* Create the pattern that is presented in nds32-multiple.md. */
100 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
102 for (par_index = 0; par_index < count; par_index++)
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);
111 XVECEXP (result, 0, par_index) = gen_rtx_SET (reg, mem);
114 return result;
118 nds32_expand_store_multiple (int base_regno, int count,
119 rtx base_addr, rtx basemem)
121 int par_index;
122 int offset;
123 rtx result;
124 rtx new_addr, mem, reg;
126 /* Create the pattern that is presented in nds32-multiple.md. */
128 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
130 for (par_index = 0; par_index < count; par_index++)
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);
139 XVECEXP (result, 0, par_index) = gen_rtx_SET (mem, reg);
142 return result;
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. */
150 nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment)
152 HOST_WIDE_INT in_words, out_words;
153 rtx dst_base_reg, src_base_reg;
154 int maximum_bytes;
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;
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;
181 dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0));
182 src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0));
184 out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD;
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));
189 /* Successfully create patterns, return 1. */
190 return 1;
193 /* ------------------------------------------------------------------------ */