]>
Commit | Line | Data |
---|---|---|
eae21ed1 | 1 | ;; Load/Store Multiple patterns description of Andes NDS32 cpu for GNU compiler |
f1717362 | 2 | ;; Copyright (C) 2012-2016 Free Software Foundation, Inc. |
eae21ed1 | 3 | ;; Contributed by Andes Technology Corporation.for NDS32. |
4 | ;; | |
5 | ;; This file is part of GCC. | |
6 | ;; | |
7 | ;; GCC is free software; you can redistribute it and/or modify it | |
8 | ;; under the terms of the GNU General Public License as published | |
9 | ;; by the Free Software Foundation; either version 3, or (at your | |
10 | ;; option) any later version. | |
11 | ;; | |
12 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT | |
13 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | ;; License for more details. | |
16 | ;; | |
17 | ;; You should have received a copy of the GNU General Public License | |
18 | ;; along with GCC; see the file COPYING3. If not see | |
19 | ;; <http://www.gnu.org/licenses/>. | |
20 | ||
21 | ||
22 | ;; Load Multiple Insns. | |
23 | ;; | |
24 | ;; operands[0] is the first of the consecutive registers. | |
25 | ;; operands[1] is the first memory location. | |
26 | ;; operands[2] is the number of consecutive registers. | |
27 | ||
28 | (define_expand "load_multiple" | |
29 | [(match_par_dup 3 [(set (match_operand:SI 0 "" "") | |
30 | (match_operand:SI 1 "" "")) | |
31 | (use (match_operand:SI 2 "" ""))])] | |
32 | "" | |
33 | { | |
34 | int maximum; | |
35 | ||
36 | /* Because reduced-set regsiters has few registers | |
37 | (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot | |
38 | be used for register allocation), | |
39 | using 8 registers for load_multiple may easily consume all of them. | |
40 | It makes register allocation/spilling hard to work. | |
41 | So we only allow maximum=4 registers for load_multiple | |
42 | under reduced-set registers. */ | |
43 | if (TARGET_REDUCED_REGS) | |
44 | maximum = 4; | |
45 | else | |
46 | maximum = 8; | |
47 | ||
48 | /* Here are the conditions that must be all passed, | |
49 | otherwise we have to FAIL this rtx generation: | |
50 | 1. The number of consecutive registers must be integer. | |
51 | 2. Maximum 4 or 8 registers for lmw.bi instruction | |
52 | (based on this nds32-multiple.md design). | |
53 | 3. Minimum 2 registers for lmw.bi instruction | |
54 | (based on this nds32-multiple.md design). | |
55 | 4. operands[0] must be register for sure. | |
56 | 5. operands[1] must be memory for sure. | |
57 | 6. Do not cross $r15 register because it is not allocatable. */ | |
58 | if (GET_CODE (operands[2]) != CONST_INT | |
59 | || INTVAL (operands[2]) > maximum | |
60 | || INTVAL (operands[2]) < 2 | |
61 | || GET_CODE (operands[0]) != REG | |
62 | || GET_CODE (operands[1]) != MEM | |
63 | || REGNO (operands[0]) + INTVAL (operands[2]) > TA_REGNUM) | |
64 | FAIL; | |
65 | ||
66 | /* For (mem addr), we force_reg on addr here, | |
67 | so that nds32_expand_load_multiple can easily use it. */ | |
68 | operands[3] = nds32_expand_load_multiple (REGNO (operands[0]), | |
69 | INTVAL (operands[2]), | |
70 | force_reg (SImode, | |
71 | XEXP (operands[1], 0)), | |
72 | operands[1]); | |
73 | }) | |
74 | ||
75 | ;; Ordinary Load Multiple. | |
76 | ||
77 | (define_insn "*lmwsi8" | |
78 | [(match_parallel 0 "nds32_load_multiple_operation" | |
79 | [(set (match_operand:SI 2 "register_operand" "") | |
80 | (mem:SI (match_operand:SI 1 "register_operand" "r"))) | |
81 | (set (match_operand:SI 3 "register_operand" "") | |
82 | (mem:SI (plus:SI (match_dup 1) (const_int 4)))) | |
83 | (set (match_operand:SI 4 "register_operand" "") | |
84 | (mem:SI (plus:SI (match_dup 1) (const_int 8)))) | |
85 | (set (match_operand:SI 5 "register_operand" "") | |
86 | (mem:SI (plus:SI (match_dup 1) (const_int 12)))) | |
87 | (set (match_operand:SI 6 "register_operand" "") | |
88 | (mem:SI (plus:SI (match_dup 1) (const_int 16)))) | |
89 | (set (match_operand:SI 7 "register_operand" "") | |
90 | (mem:SI (plus:SI (match_dup 1) (const_int 20)))) | |
91 | (set (match_operand:SI 8 "register_operand" "") | |
92 | (mem:SI (plus:SI (match_dup 1) (const_int 24)))) | |
93 | (set (match_operand:SI 9 "register_operand" "") | |
94 | (mem:SI (plus:SI (match_dup 1) (const_int 28))))])] | |
95 | "(XVECLEN (operands[0], 0) == 8)" | |
96 | "lmw.bi\t%2, [%1], %9, 0x0" | |
97 | [(set_attr "type" "load") | |
98 | (set_attr "length" "4")] | |
99 | ) | |
100 | ||
101 | (define_insn "*lmwsi7" | |
102 | [(match_parallel 0 "nds32_load_multiple_operation" | |
103 | [(set (match_operand:SI 2 "register_operand" "") | |
104 | (mem:SI (match_operand:SI 1 "register_operand" "r"))) | |
105 | (set (match_operand:SI 3 "register_operand" "") | |
106 | (mem:SI (plus:SI (match_dup 1) (const_int 4)))) | |
107 | (set (match_operand:SI 4 "register_operand" "") | |
108 | (mem:SI (plus:SI (match_dup 1) (const_int 8)))) | |
109 | (set (match_operand:SI 5 "register_operand" "") | |
110 | (mem:SI (plus:SI (match_dup 1) (const_int 12)))) | |
111 | (set (match_operand:SI 6 "register_operand" "") | |
112 | (mem:SI (plus:SI (match_dup 1) (const_int 16)))) | |
113 | (set (match_operand:SI 7 "register_operand" "") | |
114 | (mem:SI (plus:SI (match_dup 1) (const_int 20)))) | |
115 | (set (match_operand:SI 8 "register_operand" "") | |
116 | (mem:SI (plus:SI (match_dup 1) (const_int 24))))])] | |
117 | "(XVECLEN (operands[0], 0) == 7)" | |
118 | "lmw.bi\t%2, [%1], %8, 0x0" | |
119 | [(set_attr "type" "load") | |
120 | (set_attr "length" "4")] | |
121 | ) | |
122 | ||
123 | (define_insn "*lmwsi6" | |
124 | [(match_parallel 0 "nds32_load_multiple_operation" | |
125 | [(set (match_operand:SI 2 "register_operand" "") | |
126 | (mem:SI (match_operand:SI 1 "register_operand" "r"))) | |
127 | (set (match_operand:SI 3 "register_operand" "") | |
128 | (mem:SI (plus:SI (match_dup 1) (const_int 4)))) | |
129 | (set (match_operand:SI 4 "register_operand" "") | |
130 | (mem:SI (plus:SI (match_dup 1) (const_int 8)))) | |
131 | (set (match_operand:SI 5 "register_operand" "") | |
132 | (mem:SI (plus:SI (match_dup 1) (const_int 12)))) | |
133 | (set (match_operand:SI 6 "register_operand" "") | |
134 | (mem:SI (plus:SI (match_dup 1) (const_int 16)))) | |
135 | (set (match_operand:SI 7 "register_operand" "") | |
136 | (mem:SI (plus:SI (match_dup 1) (const_int 20))))])] | |
137 | "(XVECLEN (operands[0], 0) == 6)" | |
138 | "lmw.bi\t%2, [%1], %7, 0x0" | |
139 | [(set_attr "type" "load") | |
140 | (set_attr "length" "4")] | |
141 | ) | |
142 | ||
143 | (define_insn "*lmwsi5" | |
144 | [(match_parallel 0 "nds32_load_multiple_operation" | |
145 | [(set (match_operand:SI 2 "register_operand" "") | |
146 | (mem:SI (match_operand:SI 1 "register_operand" "r"))) | |
147 | (set (match_operand:SI 3 "register_operand" "") | |
148 | (mem:SI (plus:SI (match_dup 1) (const_int 4)))) | |
149 | (set (match_operand:SI 4 "register_operand" "") | |
150 | (mem:SI (plus:SI (match_dup 1) (const_int 8)))) | |
151 | (set (match_operand:SI 5 "register_operand" "") | |
152 | (mem:SI (plus:SI (match_dup 1) (const_int 12)))) | |
153 | (set (match_operand:SI 6 "register_operand" "") | |
154 | (mem:SI (plus:SI (match_dup 1) (const_int 16))))])] | |
155 | "(XVECLEN (operands[0], 0) == 5)" | |
156 | "lmw.bi\t%2, [%1], %6, 0x0" | |
157 | [(set_attr "type" "load") | |
158 | (set_attr "length" "4")] | |
159 | ) | |
160 | ||
161 | (define_insn "*lmwsi4" | |
162 | [(match_parallel 0 "nds32_load_multiple_operation" | |
163 | [(set (match_operand:SI 2 "register_operand" "") | |
164 | (mem:SI (match_operand:SI 1 "register_operand" "r"))) | |
165 | (set (match_operand:SI 3 "register_operand" "") | |
166 | (mem:SI (plus:SI (match_dup 1) (const_int 4)))) | |
167 | (set (match_operand:SI 4 "register_operand" "") | |
168 | (mem:SI (plus:SI (match_dup 1) (const_int 8)))) | |
169 | (set (match_operand:SI 5 "register_operand" "") | |
170 | (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] | |
171 | "(XVECLEN (operands[0], 0) == 4)" | |
172 | "lmw.bi\t%2, [%1], %5, 0x0" | |
173 | [(set_attr "type" "load") | |
174 | (set_attr "length" "4")] | |
175 | ) | |
176 | ||
177 | (define_insn "*lmwsi3" | |
178 | [(match_parallel 0 "nds32_load_multiple_operation" | |
179 | [(set (match_operand:SI 2 "register_operand" "") | |
180 | (mem:SI (match_operand:SI 1 "register_operand" "r"))) | |
181 | (set (match_operand:SI 3 "register_operand" "") | |
182 | (mem:SI (plus:SI (match_dup 1) (const_int 4)))) | |
183 | (set (match_operand:SI 4 "register_operand" "") | |
184 | (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] | |
185 | "(XVECLEN (operands[0], 0) == 3)" | |
186 | "lmw.bi\t%2, [%1], %4, 0x0" | |
187 | [(set_attr "type" "load") | |
188 | (set_attr "length" "4")] | |
189 | ) | |
190 | ||
191 | (define_insn "*lmwsi2" | |
192 | [(match_parallel 0 "nds32_load_multiple_operation" | |
193 | [(set (match_operand:SI 2 "register_operand" "") | |
194 | (mem:SI (match_operand:SI 1 "register_operand" "r"))) | |
195 | (set (match_operand:SI 3 "register_operand" "") | |
196 | (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] | |
197 | "(XVECLEN (operands[0], 0) == 2)" | |
198 | "lmw.bi\t%2, [%1], %3, 0x0" | |
199 | [(set_attr "type" "load") | |
200 | (set_attr "length" "4")] | |
201 | ) | |
202 | ||
203 | ||
204 | ;; Store Multiple Insns. | |
205 | ;; | |
206 | ;; operands[0] is the first memory location. | |
207 | ;; opernads[1] is the first of the consecutive registers. | |
208 | ;; operands[2] is the number of consecutive registers. | |
209 | ||
210 | (define_expand "store_multiple" | |
211 | [(match_par_dup 3 [(set (match_operand:SI 0 "" "") | |
212 | (match_operand:SI 1 "" "")) | |
213 | (use (match_operand:SI 2 "" ""))])] | |
214 | "" | |
215 | { | |
216 | int maximum; | |
217 | ||
218 | /* Because reduced-set regsiters has few registers | |
219 | (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot | |
220 | be used for register allocation), | |
221 | using 8 registers for store_multiple may easily consume all of them. | |
222 | It makes register allocation/spilling hard to work. | |
223 | So we only allow maximum=4 registers for store_multiple | |
224 | under reduced-set registers. */ | |
225 | if (TARGET_REDUCED_REGS) | |
226 | maximum = 4; | |
227 | else | |
228 | maximum = 8; | |
229 | ||
230 | /* Here are the conditions that must be all passed, | |
231 | otherwise we have to FAIL this rtx generation: | |
232 | 1. The number of consecutive registers must be integer. | |
233 | 2. Maximum 4 or 8 registers for smw.bi instruction | |
234 | (based on this nds32-multiple.md design). | |
235 | 3. Minimum 2 registers for smw.bi instruction | |
236 | (based on this nds32-multiple.md design). | |
237 | 4. operands[0] must be memory for sure. | |
238 | 5. operands[1] must be register for sure. | |
239 | 6. Do not cross $r15 register because it is not allocatable. */ | |
240 | if (GET_CODE (operands[2]) != CONST_INT | |
241 | || INTVAL (operands[2]) > maximum | |
242 | || INTVAL (operands[2]) < 2 | |
243 | || GET_CODE (operands[0]) != MEM | |
244 | || GET_CODE (operands[1]) != REG | |
245 | || REGNO (operands[1]) + INTVAL (operands[2]) > TA_REGNUM) | |
246 | FAIL; | |
247 | ||
248 | /* For (mem addr), we force_reg on addr here, | |
249 | so that nds32_expand_store_multiple can easily use it. */ | |
250 | operands[3] = nds32_expand_store_multiple (REGNO (operands[1]), | |
251 | INTVAL (operands[2]), | |
252 | force_reg (SImode, | |
253 | XEXP (operands[0], 0)), | |
254 | operands[0]); | |
255 | }) | |
256 | ||
257 | ;; Ordinary Store Multiple. | |
258 | ||
259 | (define_insn "*stmsi8" | |
260 | [(match_parallel 0 "nds32_store_multiple_operation" | |
261 | [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
262 | (match_operand:SI 2 "register_operand" "")) | |
263 | (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) | |
264 | (match_operand:SI 3 "register_operand" "")) | |
265 | (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) | |
266 | (match_operand:SI 4 "register_operand" "")) | |
267 | (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) | |
268 | (match_operand:SI 5 "register_operand" "")) | |
269 | (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) | |
270 | (match_operand:SI 6 "register_operand" "")) | |
271 | (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) | |
272 | (match_operand:SI 7 "register_operand" "")) | |
273 | (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) | |
274 | (match_operand:SI 8 "register_operand" "")) | |
275 | (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) | |
276 | (match_operand:SI 9 "register_operand" ""))])] | |
277 | "(XVECLEN (operands[0], 0) == 8)" | |
278 | "smw.bi\t%2, [%1], %9, 0x0" | |
279 | [(set_attr "type" "store") | |
280 | (set_attr "length" "4")] | |
281 | ) | |
282 | ||
283 | (define_insn "*stmsi7" | |
284 | [(match_parallel 0 "nds32_store_multiple_operation" | |
285 | [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
286 | (match_operand:SI 2 "register_operand" "")) | |
287 | (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) | |
288 | (match_operand:SI 3 "register_operand" "")) | |
289 | (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) | |
290 | (match_operand:SI 4 "register_operand" "")) | |
291 | (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) | |
292 | (match_operand:SI 5 "register_operand" "")) | |
293 | (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) | |
294 | (match_operand:SI 6 "register_operand" "")) | |
295 | (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) | |
296 | (match_operand:SI 7 "register_operand" "")) | |
297 | (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) | |
298 | (match_operand:SI 8 "register_operand" ""))])] | |
299 | "(XVECLEN (operands[0], 0) == 7)" | |
300 | "smw.bi\t%2, [%1], %8, 0x0" | |
301 | [(set_attr "type" "store") | |
302 | (set_attr "length" "4")] | |
303 | ) | |
304 | ||
305 | (define_insn "*stmsi6" | |
306 | [(match_parallel 0 "nds32_store_multiple_operation" | |
307 | [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
308 | (match_operand:SI 2 "register_operand" "")) | |
309 | (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) | |
310 | (match_operand:SI 3 "register_operand" "")) | |
311 | (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) | |
312 | (match_operand:SI 4 "register_operand" "")) | |
313 | (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) | |
314 | (match_operand:SI 5 "register_operand" "")) | |
315 | (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) | |
316 | (match_operand:SI 6 "register_operand" "")) | |
317 | (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) | |
318 | (match_operand:SI 7 "register_operand" ""))])] | |
319 | "(XVECLEN (operands[0], 0) == 6)" | |
320 | "smw.bi\t%2, [%1], %7, 0x0" | |
321 | [(set_attr "type" "store") | |
322 | (set_attr "length" "4")] | |
323 | ) | |
324 | ||
325 | (define_insn "*stmsi5" | |
326 | [(match_parallel 0 "nds32_store_multiple_operation" | |
327 | [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
328 | (match_operand:SI 2 "register_operand" "")) | |
329 | (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) | |
330 | (match_operand:SI 3 "register_operand" "")) | |
331 | (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) | |
332 | (match_operand:SI 4 "register_operand" "")) | |
333 | (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) | |
334 | (match_operand:SI 5 "register_operand" "")) | |
335 | (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) | |
336 | (match_operand:SI 6 "register_operand" ""))])] | |
337 | "(XVECLEN (operands[0], 0) == 5)" | |
338 | "smw.bi\t%2, [%1], %6, 0x0" | |
339 | [(set_attr "type" "store") | |
340 | (set_attr "length" "4")] | |
341 | ) | |
342 | ||
343 | (define_insn "*stmsi4" | |
344 | [(match_parallel 0 "nds32_store_multiple_operation" | |
345 | [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
346 | (match_operand:SI 2 "register_operand" "")) | |
347 | (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) | |
348 | (match_operand:SI 3 "register_operand" "")) | |
349 | (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) | |
350 | (match_operand:SI 4 "register_operand" "")) | |
351 | (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) | |
352 | (match_operand:SI 5 "register_operand" ""))])] | |
353 | "(XVECLEN (operands[0], 0) == 4)" | |
354 | "smw.bi\t%2, [%1], %5, 0x0" | |
355 | [(set_attr "type" "store") | |
356 | (set_attr "length" "4")] | |
357 | ) | |
358 | ||
359 | (define_insn "*stmsi3" | |
360 | [(match_parallel 0 "nds32_store_multiple_operation" | |
361 | [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
362 | (match_operand:SI 2 "register_operand" "")) | |
363 | (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) | |
364 | (match_operand:SI 3 "register_operand" "")) | |
365 | (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) | |
366 | (match_operand:SI 4 "register_operand" ""))])] | |
367 | "(XVECLEN (operands[0], 0) == 3)" | |
368 | "smw.bi\t%2, [%1], %4, 0x0" | |
369 | [(set_attr "type" "store") | |
370 | (set_attr "length" "4")] | |
371 | ) | |
372 | ||
373 | (define_insn "*stmsi2" | |
374 | [(match_parallel 0 "nds32_store_multiple_operation" | |
375 | [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
376 | (match_operand:SI 2 "register_operand" "")) | |
377 | (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) | |
378 | (match_operand:SI 3 "register_operand" ""))])] | |
379 | "(XVECLEN (operands[0], 0) == 2)" | |
380 | "smw.bi\t%2, [%1], %3, 0x0" | |
381 | [(set_attr "type" "store") | |
382 | (set_attr "length" "4")] | |
383 | ) | |
384 | ||
385 | ;; Move a block of memory if it is word aligned and MORE than 2 words long. | |
386 | ;; We could let this apply for blocks of less than this, but it clobbers so | |
387 | ;; many registers that there is then probably a better way. | |
388 | ;; | |
389 | ;; operands[0] is the destination block of memory. | |
390 | ;; operands[1] is the source block of memory. | |
391 | ;; operands[2] is the number of bytes to move. | |
392 | ;; operands[3] is the known shared alignment. | |
393 | ||
394 | (define_expand "movmemqi" | |
395 | [(match_operand:BLK 0 "general_operand" "") | |
396 | (match_operand:BLK 1 "general_operand" "") | |
397 | (match_operand:SI 2 "const_int_operand" "") | |
398 | (match_operand:SI 3 "const_int_operand" "")] | |
399 | "" | |
400 | { | |
401 | if (nds32_expand_movmemqi (operands[0], | |
402 | operands[1], | |
403 | operands[2], | |
404 | operands[3])) | |
405 | DONE; | |
406 | ||
407 | FAIL; | |
408 | }) | |
409 | ||
410 | ;; ------------------------------------------------------------------------ |