* gcc-interface/trans.c (process_freeze_entity): Be prepared for a
[official-gcc.git] / gcc / config / nds32 / nds32-memory-manipulation.c
blob5bc1f9b5396e4af64cc7c847db1675b182a0ebf0
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-2017 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 "backend.h"
28 #include "target.h"
29 #include "rtl.h"
30 #include "memmodel.h"
31 #include "emit-rtl.h"
32 #include "explow.h"
34 /* ------------------------------------------------------------------------ */
36 /* Functions to expand load_multiple and store_multiple.
37 They are auxiliary extern functions to help create rtx template.
38 Check nds32-multiple.md file for the patterns. */
39 rtx
40 nds32_expand_load_multiple (int base_regno, int count,
41 rtx base_addr, rtx basemem)
43 int par_index;
44 int offset;
45 rtx result;
46 rtx new_addr, mem, reg;
48 /* Create the pattern that is presented in nds32-multiple.md. */
50 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
52 for (par_index = 0; par_index < count; par_index++)
54 offset = par_index * 4;
55 /* 4-byte for loading data to each register. */
56 new_addr = plus_constant (Pmode, base_addr, offset);
57 mem = adjust_automodify_address_nv (basemem, SImode,
58 new_addr, offset);
59 reg = gen_rtx_REG (SImode, base_regno + par_index);
61 XVECEXP (result, 0, par_index) = gen_rtx_SET (reg, mem);
64 return result;
67 rtx
68 nds32_expand_store_multiple (int base_regno, int count,
69 rtx base_addr, rtx basemem)
71 int par_index;
72 int offset;
73 rtx result;
74 rtx new_addr, mem, reg;
76 /* Create the pattern that is presented in nds32-multiple.md. */
78 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
80 for (par_index = 0; par_index < count; par_index++)
82 offset = par_index * 4;
83 /* 4-byte for storing data to memory. */
84 new_addr = plus_constant (Pmode, base_addr, offset);
85 mem = adjust_automodify_address_nv (basemem, SImode,
86 new_addr, offset);
87 reg = gen_rtx_REG (SImode, base_regno + par_index);
89 XVECEXP (result, 0, par_index) = gen_rtx_SET (mem, reg);
92 return result;
95 /* Function to move block memory content by
96 using load_multiple and store_multiple.
97 This is auxiliary extern function to help create rtx template.
98 Check nds32-multiple.md file for the patterns. */
99 int
100 nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment)
102 HOST_WIDE_INT in_words, out_words;
103 rtx dst_base_reg, src_base_reg;
104 int maximum_bytes;
106 /* Because reduced-set regsiters has few registers
107 (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31'
108 cannot be used for register allocation),
109 using 8 registers (32 bytes) for moving memory block
110 may easily consume all of them.
111 It makes register allocation/spilling hard to work.
112 So we only allow maximum=4 registers (16 bytes) for
113 moving memory block under reduced-set registers. */
114 if (TARGET_REDUCED_REGS)
115 maximum_bytes = 16;
116 else
117 maximum_bytes = 32;
119 /* 1. Total_bytes is integer for sure.
120 2. Alignment is integer for sure.
121 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes.
122 4. Requires (n * 4) block size.
123 5. Requires 4-byte alignment. */
124 if (GET_CODE (total_bytes) != CONST_INT
125 || GET_CODE (alignment) != CONST_INT
126 || INTVAL (total_bytes) > maximum_bytes
127 || INTVAL (total_bytes) & 3
128 || INTVAL (alignment) & 3)
129 return 0;
131 dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0));
132 src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0));
134 out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD;
136 emit_insn (nds32_expand_load_multiple (0, in_words, src_base_reg, srcmem));
137 emit_insn (nds32_expand_store_multiple (0, out_words, dst_base_reg, dstmem));
139 /* Successfully create patterns, return 1. */
140 return 1;
143 /* ------------------------------------------------------------------------ */