xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/nds32/nds32-memory-manipulation.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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