111
|
1 ;; Machine description of Andes NDS32 cpu for GNU compiler
|
131
|
2 ;; Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
111
|
3 ;; Contributed by Andes Technology Corporation.
|
|
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 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
|
|
22
|
|
23 ;; Include predicates definition.
|
|
24 (include "predicates.md")
|
|
25
|
|
26 ;; Include constraints definition.
|
|
27 (include "constraints.md")
|
|
28
|
|
29 ;; Include iterators definition.
|
|
30 (include "iterators.md")
|
|
31
|
|
32 ;; Include pipelines definition.
|
|
33 (include "pipelines.md")
|
|
34
|
|
35
|
|
36 ;; Include constants definition.
|
|
37 (include "constants.md")
|
|
38
|
|
39
|
|
40 ;; Include intrinsic functions definition.
|
|
41 (include "nds32-intrinsic.md")
|
|
42
|
|
43 ;; Include block move for nds32 multiple load/store behavior.
|
|
44 (include "nds32-multiple.md")
|
|
45
|
|
46 ;; Include DImode/DFmode operations.
|
|
47 (include "nds32-doubleword.md")
|
|
48
|
131
|
49 ;; Include floating-point patterns.
|
|
50 (include "nds32-fpu.md")
|
|
51
|
111
|
52 ;; Include peephole patterns.
|
|
53 (include "nds32-peephole2.md")
|
|
54
|
|
55
|
131
|
56 ;; ------------------------------------------------------------------------
|
|
57
|
|
58 ;; CPU pipeline model.
|
|
59 (define_attr "pipeline_model" "n7,n8,e8,n9,n10,graywolf,n13,simple"
|
|
60 (const
|
|
61 (cond [(match_test "nds32_cpu_option == CPU_N7") (const_string "n7")
|
|
62 (match_test "nds32_cpu_option == CPU_E8") (const_string "e8")
|
|
63 (match_test "nds32_cpu_option == CPU_N6 || nds32_cpu_option == CPU_N8") (const_string "n8")
|
|
64 (match_test "nds32_cpu_option == CPU_N9") (const_string "n9")
|
|
65 (match_test "nds32_cpu_option == CPU_N10") (const_string "n10")
|
|
66 (match_test "nds32_cpu_option == CPU_GRAYWOLF") (const_string "graywolf")
|
|
67 (match_test "nds32_cpu_option == CPU_N12") (const_string "n13")
|
|
68 (match_test "nds32_cpu_option == CPU_N13") (const_string "n13")
|
|
69 (match_test "nds32_cpu_option == CPU_SIMPLE") (const_string "simple")]
|
|
70 (const_string "n9"))))
|
|
71
|
111
|
72 ;; Insn type, it is used to default other attribute values.
|
|
73 (define_attr "type"
|
131
|
74 "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\
|
|
75 falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore,\
|
|
76 dalu,dalu64,daluround,dcmp,dclip,dmul,dmac,dinsb,dpack,dbpick,dwext"
|
111
|
77 (const_string "unknown"))
|
|
78
|
131
|
79 ;; Insn sub-type
|
|
80 (define_attr "subtype"
|
|
81 "simple,shift,saturation"
|
|
82 (const_string "simple"))
|
111
|
83
|
|
84 ;; Length, in bytes, default is 4-bytes.
|
|
85 (define_attr "length" "" (const_int 4))
|
|
86
|
131
|
87 ;; Indicate the amount of micro instructions.
|
|
88 (define_attr "combo"
|
|
89 "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25"
|
|
90 (const_string "1"))
|
|
91
|
|
92 ;; Insn in which feature set, it is used to enable/disable insn alternatives.
|
|
93 ;; v1 : Baseline Instructions
|
|
94 ;; v2 : Baseline Version 2 Instructions
|
|
95 ;; v3m : Baseline Version 3m Instructions
|
|
96 ;; v3 : Baseline Version 3 Instructions
|
|
97 ;; pe1 : Performance Extension Instructions
|
|
98 ;; pe2 : Performance Extension Version 2 Instructions
|
|
99 ;; se : String Extension instructions
|
|
100 (define_attr "feature"
|
|
101 "v1,v2,v3m,v3,pe1,pe2,se,fpu"
|
|
102 (const_string "v1"))
|
111
|
103
|
|
104 ;; Enabled, which is used to enable/disable insn alternatives.
|
|
105 ;; Note that we use length and TARGET_16_BIT here as criteria.
|
131
|
106 ;; If the instruction pattern already check TARGET_16_BIT to determine
|
|
107 ;; the length by itself, its enabled attribute should be customized to
|
|
108 ;; avoid the conflict between length attribute and this default setting.
|
|
109 (define_attr "enabled" "no,yes"
|
|
110 (if_then_else
|
|
111 (and (eq_attr "length" "2")
|
|
112 (match_test "!TARGET_16_BIT"))
|
|
113 (const_string "no")
|
|
114 (cond [(eq_attr "feature" "v1") (const_string "yes")
|
|
115 (eq_attr "feature" "v2") (if_then_else (match_test "TARGET_ISA_V2 || TARGET_ISA_V3 || TARGET_ISA_V3M")
|
|
116 (const_string "yes")
|
|
117 (const_string "no"))
|
|
118 (eq_attr "feature" "v3") (if_then_else (match_test "TARGET_ISA_V3")
|
|
119 (const_string "yes")
|
|
120 (const_string "no"))
|
|
121 (eq_attr "feature" "v3m") (if_then_else (match_test "TARGET_ISA_V3 || TARGET_ISA_V3M")
|
|
122 (const_string "yes")
|
|
123 (const_string "no"))
|
|
124 (eq_attr "feature" "pe1") (if_then_else (match_test "TARGET_EXT_PERF")
|
|
125 (const_string "yes")
|
|
126 (const_string "no"))
|
|
127 (eq_attr "feature" "pe2") (if_then_else (match_test "TARGET_EXT_PERF2")
|
|
128 (const_string "yes")
|
|
129 (const_string "no"))
|
|
130 (eq_attr "feature" "se") (if_then_else (match_test "TARGET_EXT_STRING")
|
|
131 (const_string "yes")
|
|
132 (const_string "no"))
|
|
133 (eq_attr "feature" "fpu") (if_then_else (match_test "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE")
|
|
134 (const_string "yes")
|
|
135 (const_string "no"))]
|
|
136 (const_string "yes"))))
|
111
|
137
|
|
138
|
|
139 ;; ----------------------------------------------------------------------------
|
|
140
|
131
|
141 (include "nds32-dspext.md")
|
111
|
142
|
|
143 ;; Move instructions.
|
|
144
|
|
145 ;; For QImode and HImode, the immediate value can be fit in imm20s.
|
|
146 ;; So there is no need to split rtx for QI and HI patterns.
|
|
147
|
131
|
148 (define_expand "mov<mode>"
|
|
149 [(set (match_operand:QIHI 0 "general_operand" "")
|
|
150 (match_operand:QIHI 1 "general_operand" ""))]
|
111
|
151 ""
|
|
152 {
|
|
153 /* Need to force register if mem <- !reg. */
|
|
154 if (MEM_P (operands[0]) && !REG_P (operands[1]))
|
131
|
155 operands[1] = force_reg (<MODE>mode, operands[1]);
|
|
156
|
|
157 if (MEM_P (operands[1]) && optimize > 0)
|
|
158 {
|
|
159 rtx reg = gen_reg_rtx (SImode);
|
|
160
|
|
161 emit_insn (gen_zero_extend<mode>si2 (reg, operands[1]));
|
|
162 operands[1] = gen_lowpart (<MODE>mode, reg);
|
|
163 }
|
111
|
164 })
|
|
165
|
131
|
166 (define_expand "movmisalign<mode>"
|
|
167 [(set (match_operand:SIDI 0 "general_operand" "")
|
|
168 (match_operand:SIDI 1 "general_operand" ""))]
|
111
|
169 ""
|
|
170 {
|
131
|
171 rtx addr;
|
111
|
172 if (MEM_P (operands[0]) && !REG_P (operands[1]))
|
131
|
173 operands[1] = force_reg (<MODE>mode, operands[1]);
|
|
174
|
|
175 if (MEM_P (operands[0]))
|
|
176 {
|
|
177 addr = force_reg (Pmode, XEXP (operands[0], 0));
|
|
178 emit_insn (gen_unaligned_store<mode> (addr, operands[1]));
|
|
179 }
|
|
180 else
|
|
181 {
|
|
182 addr = force_reg (Pmode, XEXP (operands[1], 0));
|
|
183 emit_insn (gen_unaligned_load<mode> (operands[0], addr));
|
|
184 }
|
|
185 DONE;
|
111
|
186 })
|
|
187
|
|
188 (define_expand "movsi"
|
|
189 [(set (match_operand:SI 0 "general_operand" "")
|
|
190 (match_operand:SI 1 "general_operand" ""))]
|
|
191 ""
|
|
192 {
|
|
193 /* Need to force register if mem <- !reg. */
|
|
194 if (MEM_P (operands[0]) && !REG_P (operands[1]))
|
|
195 operands[1] = force_reg (SImode, operands[1]);
|
|
196
|
|
197 /* If operands[1] is a large constant and cannot be performed
|
|
198 by a single instruction, we need to split it. */
|
|
199 if (CONST_INT_P (operands[1])
|
|
200 && !satisfies_constraint_Is20 (operands[1])
|
|
201 && !satisfies_constraint_Ihig (operands[1]))
|
|
202 {
|
|
203 rtx high20_rtx;
|
|
204 HOST_WIDE_INT low12_int;
|
|
205 rtx tmp_rtx;
|
|
206
|
|
207 tmp_rtx = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
|
|
208
|
|
209 high20_rtx = gen_int_mode ((INTVAL (operands[1]) >> 12) << 12, SImode);
|
|
210 low12_int = INTVAL (operands[1]) & 0xfff;
|
|
211
|
|
212 emit_move_insn (tmp_rtx, high20_rtx);
|
|
213 emit_move_insn (operands[0], plus_constant (SImode,
|
|
214 tmp_rtx,
|
|
215 low12_int));
|
|
216 DONE;
|
|
217 }
|
131
|
218
|
|
219 if ((REG_P (operands[0]) || GET_CODE (operands[0]) == SUBREG)
|
|
220 && SYMBOLIC_CONST_P (operands[1]))
|
|
221 {
|
|
222 if (TARGET_ICT_MODEL_LARGE
|
|
223 && nds32_indirect_call_referenced_p (operands[1]))
|
|
224 {
|
|
225 nds32_expand_ict_move (operands);
|
|
226 DONE;
|
|
227 }
|
|
228 else if (nds32_tls_referenced_p (operands [1]))
|
|
229 {
|
|
230 nds32_expand_tls_move (operands);
|
|
231 DONE;
|
|
232 }
|
|
233 else if (flag_pic)
|
|
234 {
|
|
235 nds32_expand_pic_move (operands);
|
|
236 DONE;
|
|
237 }
|
|
238 }
|
111
|
239 })
|
|
240
|
|
241 (define_insn "*mov<mode>"
|
131
|
242 [(set (match_operand:QIHISI 0 "nonimmediate_operand" "=r, r,U45,U33,U37,U45, m, l, l, l, d, d, r, d, r, r, r, *f, *f, r, *f, Q")
|
|
243 (match_operand:QIHISI 1 "nds32_move_operand" " r, r, l, l, l, d, r,U45,U33,U37,U45,Ufe, m,Ip05, Is05, Is20, Ihig, *f, r, *f, Q, *f"))]
|
|
244 "register_operand(operands[0], <MODE>mode)
|
|
245 || register_operand(operands[1], <MODE>mode)"
|
111
|
246 {
|
|
247 switch (which_alternative)
|
|
248 {
|
|
249 case 0:
|
|
250 return "mov55\t%0, %1";
|
|
251 case 1:
|
|
252 return "ori\t%0, %1, 0";
|
|
253 case 2:
|
|
254 case 3:
|
|
255 case 4:
|
|
256 case 5:
|
|
257 return nds32_output_16bit_store (operands, <byte>);
|
|
258 case 6:
|
|
259 return nds32_output_32bit_store (operands, <byte>);
|
|
260 case 7:
|
|
261 case 8:
|
|
262 case 9:
|
|
263 case 10:
|
131
|
264 case 11:
|
111
|
265 return nds32_output_16bit_load (operands, <byte>);
|
131
|
266 case 12:
|
111
|
267 return nds32_output_32bit_load (operands, <byte>);
|
|
268 case 13:
|
131
|
269 return "movpi45\t%0, %1";
|
|
270 case 14:
|
111
|
271 return "movi55\t%0, %1";
|
131
|
272 case 15:
|
111
|
273 return "movi\t%0, %1";
|
131
|
274 case 16:
|
111
|
275 return "sethi\t%0, hi20(%1)";
|
131
|
276 case 17:
|
|
277 if (TARGET_FPU_SINGLE)
|
|
278 return "fcpyss\t%0, %1, %1";
|
|
279 else
|
|
280 return "#";
|
|
281 case 18:
|
|
282 return "fmtsr\t%1, %0";
|
|
283 case 19:
|
|
284 return "fmfsr\t%0, %1";
|
|
285 case 20:
|
|
286 return nds32_output_float_load (operands);
|
|
287 case 21:
|
|
288 return nds32_output_float_store (operands);
|
111
|
289 default:
|
|
290 gcc_unreachable ();
|
|
291 }
|
|
292 }
|
131
|
293 [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,load,alu,alu,alu,alu,fcpy,fmtsr,fmfsr,fload,fstore")
|
|
294 (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4")
|
|
295 (set_attr "feature" " v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v3m, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu")])
|
111
|
296
|
|
297
|
|
298 ;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF
|
|
299 ;; are able to match such instruction template.
|
131
|
300 (define_insn "move_addr"
|
|
301 [(set (match_operand:SI 0 "nds32_general_register_operand" "=l, r")
|
|
302 (match_operand:SI 1 "nds32_nonunspec_symbolic_operand" " i, i"))]
|
111
|
303 ""
|
|
304 "la\t%0, %1"
|
131
|
305 [(set_attr "type" "alu")
|
111
|
306 (set_attr "length" "8")])
|
|
307
|
|
308
|
131
|
309 (define_insn "sethi"
|
111
|
310 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
311 (high:SI (match_operand:SI 1 "nds32_symbolic_operand" " i")))]
|
|
312 ""
|
|
313 "sethi\t%0, hi20(%1)"
|
|
314 [(set_attr "type" "alu")
|
|
315 (set_attr "length" "4")])
|
|
316
|
|
317
|
131
|
318 (define_insn "lo_sum"
|
111
|
319 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
320 (lo_sum:SI (match_operand:SI 1 "register_operand" " r")
|
|
321 (match_operand:SI 2 "nds32_symbolic_operand" " i")))]
|
|
322 ""
|
|
323 "ori\t%0, %1, lo12(%2)"
|
|
324 [(set_attr "type" "alu")
|
|
325 (set_attr "length" "4")])
|
|
326
|
|
327
|
|
328 ;; ----------------------------------------------------------------------------
|
|
329
|
|
330 ;; Zero extension instructions.
|
|
331
|
|
332 (define_insn "zero_extend<mode>si2"
|
|
333 [(set (match_operand:SI 0 "register_operand" "=l, r, l, *r")
|
|
334 (zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, U33, m")))]
|
|
335 ""
|
|
336 {
|
|
337 switch (which_alternative)
|
|
338 {
|
|
339 case 0:
|
|
340 return "ze<size>33\t%0, %1";
|
|
341 case 1:
|
|
342 return "ze<size>\t%0, %1";
|
|
343 case 2:
|
|
344 return nds32_output_16bit_load (operands, <byte>);
|
|
345 case 3:
|
|
346 return nds32_output_32bit_load (operands, <byte>);
|
|
347
|
|
348 default:
|
|
349 gcc_unreachable ();
|
|
350 }
|
|
351 }
|
|
352 [(set_attr "type" "alu,alu,load,load")
|
|
353 (set_attr "length" " 2, 4, 2, 4")])
|
|
354
|
|
355
|
|
356 ;; Sign extension instructions.
|
|
357
|
|
358 (define_insn "extend<mode>si2"
|
|
359 [(set (match_operand:SI 0 "register_operand" "=l, r, r")
|
|
360 (sign_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, m")))]
|
|
361 ""
|
|
362 {
|
|
363 switch (which_alternative)
|
|
364 {
|
|
365 case 0:
|
|
366 return "se<size>33\t%0, %1";
|
|
367 case 1:
|
|
368 return "se<size>\t%0, %1";
|
|
369 case 2:
|
|
370 return nds32_output_32bit_load_s (operands, <byte>);
|
|
371
|
|
372 default:
|
|
373 gcc_unreachable ();
|
|
374 }
|
|
375 }
|
|
376 [(set_attr "type" "alu,alu,load")
|
|
377 (set_attr "length" " 2, 4, 4")])
|
|
378
|
|
379
|
|
380 ;; ----------------------------------------------------------------------------
|
131
|
381 (define_expand "extv"
|
|
382 [(set (match_operand 0 "register_operand" "")
|
|
383 (sign_extract (match_operand 1 "nonimmediate_operand" "")
|
|
384 (match_operand 2 "const_int_operand" "")
|
|
385 (match_operand 3 "const_int_operand" "")))]
|
|
386 ""
|
|
387 {
|
|
388 enum nds32_expand_result_type result = nds32_expand_extv (operands);
|
|
389 switch (result)
|
|
390 {
|
|
391 case EXPAND_DONE:
|
|
392 DONE;
|
|
393 break;
|
|
394 case EXPAND_FAIL:
|
|
395 FAIL;
|
|
396 break;
|
|
397 case EXPAND_CREATE_TEMPLATE:
|
|
398 break;
|
|
399 default:
|
|
400 gcc_unreachable ();
|
|
401 }
|
|
402 })
|
|
403
|
|
404 (define_expand "insv"
|
|
405 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
|
|
406 (match_operand 1 "const_int_operand" "")
|
|
407 (match_operand 2 "const_int_operand" ""))
|
|
408 (match_operand 3 "register_operand" ""))]
|
|
409 ""
|
|
410 {
|
|
411 enum nds32_expand_result_type result = nds32_expand_insv (operands);
|
|
412 switch (result)
|
|
413 {
|
|
414 case EXPAND_DONE:
|
|
415 DONE;
|
|
416 break;
|
|
417 case EXPAND_FAIL:
|
|
418 FAIL;
|
|
419 break;
|
|
420 case EXPAND_CREATE_TEMPLATE:
|
|
421 break;
|
|
422 default:
|
|
423 gcc_unreachable ();
|
|
424 }
|
|
425 })
|
111
|
426
|
|
427 ;; Arithmetic instructions.
|
|
428
|
131
|
429 (define_insn "addsi3"
|
|
430 [(set (match_operand:SI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r")
|
|
431 (plus:SI (match_operand:SI 1 "register_operand" "% 0, l, 0, l, 0, l, 0, k, r, r")
|
|
432 (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,IU06, Is15, r")))]
|
111
|
433 ""
|
|
434 {
|
|
435 switch (which_alternative)
|
|
436 {
|
|
437 case 0:
|
|
438 /* addi Rt4,Rt4,-x ==> subi45 Rt4,x
|
|
439 where 0 <= x <= 31 */
|
|
440 operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
|
|
441 return "subi45\t%0, %2";
|
|
442 case 1:
|
|
443 /* addi Rt3,Ra3,-x ==> subi333 Rt3,Ra3,x
|
|
444 where 0 <= x <= 7 */
|
|
445 operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
|
|
446 return "subi333\t%0, %1, %2";
|
|
447 case 2:
|
|
448 return "addi45\t%0, %2";
|
|
449 case 3:
|
|
450 return "addi333\t%0, %1, %2";
|
|
451 case 4:
|
|
452 return "add45\t%0, %2";
|
|
453 case 5:
|
|
454 return "add333\t%0, %1, %2";
|
|
455 case 6:
|
|
456 return "addi10.sp\t%2";
|
|
457 case 7:
|
|
458 return "addri36.sp\t%0, %2";
|
|
459 case 8:
|
|
460 return "addi\t%0, %1, %2";
|
|
461 case 9:
|
|
462 return "add\t%0, %1, %2";
|
|
463
|
|
464 default:
|
|
465 gcc_unreachable ();
|
|
466 }
|
|
467 }
|
131
|
468 [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
|
|
469 (set_attr "length" " 2, 2, 2, 2, 2, 2, 2, 2, 4, 4")
|
|
470 (set_attr "feature" " v1, v1, v1, v1, v1, v1, v2, v1, v1, v1")])
|
111
|
471
|
131
|
472 (define_insn "subsi3"
|
|
473 [(set (match_operand:SI 0 "register_operand" "=d, l, r, r")
|
|
474 (minus:SI (match_operand:SI 1 "nds32_rimm15s_operand" " 0, l, Is15, r")
|
|
475 (match_operand:SI 2 "register_operand" " r, l, r, r")))]
|
111
|
476 ""
|
|
477 "@
|
131
|
478 sub45\t%0, %2
|
|
479 sub333\t%0, %1, %2
|
|
480 subri\t%0, %2, %1
|
|
481 sub\t%0, %1, %2"
|
111
|
482 [(set_attr "type" "alu,alu,alu,alu")
|
|
483 (set_attr "length" " 2, 2, 4, 4")])
|
|
484
|
|
485
|
|
486 ;; GCC intends to simplify (plus (ashift ...) (reg))
|
|
487 ;; into (plus (mult ...) (reg)), so our matching pattern takes 'mult'
|
|
488 ;; and needs to ensure it is exact_log2 value.
|
|
489 (define_insn "*add_slli"
|
|
490 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
491 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
|
|
492 (match_operand:SI 2 "immediate_operand" " i"))
|
|
493 (match_operand:SI 3 "register_operand" " r")))]
|
131
|
494 "TARGET_ISA_V3 && optimize_size
|
111
|
495 && (exact_log2 (INTVAL (operands[2])) != -1)
|
|
496 && (exact_log2 (INTVAL (operands[2])) <= 31)"
|
|
497 {
|
|
498 /* Get floor_log2 of the immediate value
|
|
499 so that we can generate 'add_slli' instruction. */
|
|
500 operands[2] = GEN_INT (floor_log2 (INTVAL (operands[2])));
|
|
501
|
|
502 return "add_slli\t%0, %3, %1, %2";
|
|
503 }
|
131
|
504 [(set_attr "type" "alu_shift")
|
|
505 (set_attr "combo" "2")
|
|
506 (set_attr "length" "4")])
|
111
|
507
|
|
508 (define_insn "*add_srli"
|
131
|
509 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
510 (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
|
|
511 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
|
|
512 (match_operand:SI 3 "register_operand" " r")))]
|
|
513 "TARGET_ISA_V3 && optimize_size"
|
111
|
514 "add_srli\t%0, %3, %1, %2"
|
131
|
515 [(set_attr "type" "alu_shift")
|
|
516 (set_attr "combo" "2")
|
|
517 (set_attr "length" "4")])
|
111
|
518
|
|
519
|
|
520 ;; GCC intends to simplify (minus (reg) (ashift ...))
|
|
521 ;; into (minus (reg) (mult ...)), so our matching pattern takes 'mult'
|
|
522 ;; and needs to ensure it is exact_log2 value.
|
|
523 (define_insn "*sub_slli"
|
|
524 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
525 (minus:SI (match_operand:SI 1 "register_operand" " r")
|
|
526 (mult:SI (match_operand:SI 2 "register_operand" " r")
|
|
527 (match_operand:SI 3 "immediate_operand" " i"))))]
|
131
|
528 "TARGET_ISA_V3 && optimize_size
|
111
|
529 && (exact_log2 (INTVAL (operands[3])) != -1)
|
|
530 && (exact_log2 (INTVAL (operands[3])) <= 31)"
|
|
531 {
|
|
532 /* Get floor_log2 of the immediate value
|
|
533 so that we can generate 'sub_slli' instruction. */
|
|
534 operands[3] = GEN_INT (floor_log2 (INTVAL (operands[3])));
|
|
535
|
|
536 return "sub_slli\t%0, %1, %2, %3";
|
|
537 }
|
131
|
538 [(set_attr "type" "alu_shift")
|
|
539 (set_attr "combo" "2")
|
|
540 (set_attr "length" "4")])
|
111
|
541
|
|
542 (define_insn "*sub_srli"
|
131
|
543 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
544 (minus:SI (match_operand:SI 1 "register_operand" " r")
|
|
545 (lshiftrt:SI (match_operand:SI 2 "register_operand" " r")
|
|
546 (match_operand:SI 3 "nds32_imm5u_operand" " Iu05"))))]
|
|
547 "TARGET_ISA_V3 && optimize_size"
|
111
|
548 "sub_srli\t%0, %1, %2, %3"
|
131
|
549 [(set_attr "type" "alu_shift")
|
|
550 (set_attr "combo" "2")
|
|
551 (set_attr "length" "4")])
|
111
|
552
|
|
553
|
|
554 ;; Multiplication instructions.
|
|
555
|
|
556 (define_insn "mulsi3"
|
|
557 [(set (match_operand:SI 0 "register_operand" "=w, r")
|
|
558 (mult:SI (match_operand:SI 1 "register_operand" "%0, r")
|
|
559 (match_operand:SI 2 "register_operand" " w, r")))]
|
|
560 ""
|
|
561 "@
|
131
|
562 mul33\t%0, %2
|
|
563 mul\t%0, %1, %2"
|
|
564 [(set_attr "type" "mul,mul")
|
|
565 (set_attr "length" " 2, 4")
|
|
566 (set_attr "feature" "v3m, v1")])
|
111
|
567
|
|
568 (define_insn "mulsidi3"
|
|
569 [(set (match_operand:DI 0 "register_operand" "=r")
|
|
570 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r"))
|
|
571 (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
|
|
572 "TARGET_ISA_V2 || TARGET_ISA_V3"
|
|
573 "mulsr64\t%0, %1, %2"
|
131
|
574 [(set_attr "type" "mul")
|
111
|
575 (set_attr "length" "4")])
|
|
576
|
|
577 (define_insn "umulsidi3"
|
|
578 [(set (match_operand:DI 0 "register_operand" "=r")
|
|
579 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
|
|
580 (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
|
|
581 "TARGET_ISA_V2 || TARGET_ISA_V3"
|
|
582 "mulr64\t%0, %1, %2"
|
131
|
583 [(set_attr "type" "mul")
|
111
|
584 (set_attr "length" "4")])
|
|
585
|
|
586
|
|
587 ;; Multiply-accumulate instructions.
|
|
588
|
|
589 (define_insn "*maddr32_0"
|
|
590 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
591 (plus:SI (match_operand:SI 3 "register_operand" " 0")
|
|
592 (mult:SI (match_operand:SI 1 "register_operand" " r")
|
|
593 (match_operand:SI 2 "register_operand" " r"))))]
|
|
594 ""
|
|
595 "maddr32\t%0, %1, %2"
|
131
|
596 [(set_attr "type" "mac")
|
111
|
597 (set_attr "length" "4")])
|
|
598
|
|
599 (define_insn "*maddr32_1"
|
|
600 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
601 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
|
|
602 (match_operand:SI 2 "register_operand" " r"))
|
|
603 (match_operand:SI 3 "register_operand" " 0")))]
|
|
604 ""
|
|
605 "maddr32\t%0, %1, %2"
|
131
|
606 [(set_attr "type" "mac")
|
111
|
607 (set_attr "length" "4")])
|
|
608
|
|
609 (define_insn "*msubr32"
|
|
610 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
611 (minus:SI (match_operand:SI 3 "register_operand" " 0")
|
|
612 (mult:SI (match_operand:SI 1 "register_operand" " r")
|
|
613 (match_operand:SI 2 "register_operand" " r"))))]
|
|
614 ""
|
|
615 "msubr32\t%0, %1, %2"
|
131
|
616 [(set_attr "type" "mac")
|
111
|
617 (set_attr "length" "4")])
|
|
618
|
|
619
|
|
620 ;; Div Instructions.
|
|
621
|
|
622 (define_insn "divmodsi4"
|
|
623 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
624 (div:SI (match_operand:SI 1 "register_operand" " r")
|
|
625 (match_operand:SI 2 "register_operand" " r")))
|
|
626 (set (match_operand:SI 3 "register_operand" "=r")
|
|
627 (mod:SI (match_dup 1) (match_dup 2)))]
|
|
628 ""
|
|
629 "divsr\t%0, %3, %1, %2"
|
131
|
630 [(set_attr "type" "div")
|
111
|
631 (set_attr "length" "4")])
|
|
632
|
|
633 (define_insn "udivmodsi4"
|
|
634 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
635 (udiv:SI (match_operand:SI 1 "register_operand" " r")
|
|
636 (match_operand:SI 2 "register_operand" " r")))
|
|
637 (set (match_operand:SI 3 "register_operand" "=r")
|
|
638 (umod:SI (match_dup 1) (match_dup 2)))]
|
|
639 ""
|
|
640 "divr\t%0, %3, %1, %2"
|
131
|
641 [(set_attr "type" "div")
|
111
|
642 (set_attr "length" "4")])
|
|
643
|
131
|
644 ;; divsr/divr will keep quotient only when quotient and remainder is the same
|
|
645 ;; register in our ISA spec, it's can reduce 1 register presure if we don't
|
|
646 ;; want remainder.
|
|
647 (define_insn "divsi4"
|
|
648 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
649 (div:SI (match_operand:SI 1 "register_operand" " r")
|
|
650 (match_operand:SI 2 "register_operand" " r")))]
|
|
651 ""
|
|
652 "divsr\t%0, %0, %1, %2"
|
|
653 [(set_attr "type" "div")
|
|
654 (set_attr "length" "4")])
|
|
655
|
|
656 (define_insn "udivsi4"
|
|
657 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
658 (udiv:SI (match_operand:SI 1 "register_operand" " r")
|
|
659 (match_operand:SI 2 "register_operand" " r")))]
|
|
660 ""
|
|
661 "divr\t%0, %0, %1, %2"
|
|
662 [(set_attr "type" "div")
|
|
663 (set_attr "length" "4")])
|
111
|
664
|
|
665 ;; ----------------------------------------------------------------------------
|
|
666
|
|
667 ;; Boolean instructions.
|
|
668 ;; Note: We define the DImode versions in nds32-doubleword.md.
|
|
669
|
|
670 ;; ----------------------------------------------------------------------------
|
|
671 ;; 'AND' operation
|
|
672 ;; ----------------------------------------------------------------------------
|
|
673
|
|
674 (define_insn "bitc"
|
|
675 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
676 (and:SI (not:SI (match_operand:SI 1 "register_operand" " r"))
|
|
677 (match_operand:SI 2 "register_operand" " r")))]
|
|
678 "TARGET_ISA_V3"
|
|
679 "bitc\t%0, %2, %1"
|
|
680 [(set_attr "type" "alu")
|
|
681 (set_attr "length" "4")]
|
|
682 )
|
|
683
|
131
|
684 (define_expand "andsi3"
|
|
685 [(set (match_operand:SI 0 "register_operand" "")
|
|
686 (and:SI (match_operand:SI 1 "register_operand" "")
|
|
687 (match_operand:SI 2 "nds32_reg_constant_operand" "")))]
|
|
688 ""
|
|
689 {
|
|
690 if (CONST_INT_P (operands[2])
|
|
691 && !nds32_and_operand (operands[2], SImode))
|
|
692 {
|
|
693 nds32_expand_constant (SImode, INTVAL (operands[2]),
|
|
694 operands[0], operands[1]);
|
|
695 DONE;
|
|
696 }
|
|
697 })
|
|
698
|
|
699 (define_insn "*andsi3"
|
|
700 [(set (match_operand:SI 0 "register_operand" "=l, r, l, l, l, l, l, l, r, r, r, r, r")
|
|
701 (and:SI (match_operand:SI 1 "register_operand" "%0, r, l, l, l, l, 0, 0, r, r, r, r, r")
|
|
702 (match_operand:SI 2 "nds32_and_operand" " l, r,Izeb,Izeh,Ixls,Ix11,Ibms,Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
|
111
|
703 ""
|
|
704 {
|
|
705 HOST_WIDE_INT mask = INTVAL (operands[2]);
|
|
706
|
|
707 /* 16-bit andi instructions:
|
|
708 andi Rt3,Ra3,0xff -> zeb33 Rt3,Ra3
|
|
709 andi Rt3,Ra3,0xffff -> zeh33 Rt3,Ra3
|
|
710 andi Rt3,Ra3,0x01 -> xlsb33 Rt3,Ra3
|
|
711 andi Rt3,Ra3,0x7ff -> x11b33 Rt3,Ra3
|
|
712 andi Rt3,Rt3,2^imm3u -> bmski33 Rt3,imm3u
|
|
713 andi Rt3,Rt3,(2^(imm3u+1))-1 -> fexti33 Rt3,imm3u. */
|
|
714
|
|
715 switch (which_alternative)
|
|
716 {
|
|
717 case 0:
|
|
718 return "and33\t%0, %2";
|
|
719 case 1:
|
|
720 return "and\t%0, %1, %2";
|
|
721 case 2:
|
|
722 return "zeb33\t%0, %1";
|
|
723 case 3:
|
|
724 return "zeh33\t%0, %1";
|
|
725 case 4:
|
|
726 return "xlsb33\t%0, %1";
|
|
727 case 5:
|
|
728 return "x11b33\t%0, %1";
|
|
729 case 6:
|
131
|
730 return "bmski33\t%0, %B2";
|
111
|
731 case 7:
|
|
732 operands[2] = GEN_INT (floor_log2 (mask + 1) - 1);
|
|
733 return "fexti33\t%0, %2";
|
|
734 case 8:
|
|
735 return "zeb\t%0, %1";
|
|
736 case 9:
|
|
737 return "zeh\t%0, %1";
|
|
738 case 10:
|
|
739 return "andi\t%0, %1, %2";
|
|
740 case 11:
|
|
741 operands[2] = GEN_INT (~mask);
|
|
742 return "bitci\t%0, %1, %2";
|
|
743 case 12:
|
131
|
744 return "bclr\t%0, %1, %b2";
|
111
|
745
|
|
746 default:
|
|
747 gcc_unreachable ();
|
|
748 }
|
|
749 }
|
131
|
750 [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
|
|
751 (set_attr "length" " 2, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4")
|
|
752 (set_attr "feature" "v3m, v1, v1, v1, v1, v1,v3m,v3m, v1, v1, v1, v3,pe1")])
|
111
|
753
|
|
754 (define_insn "*and_slli"
|
131
|
755 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
756 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
|
|
757 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
|
|
758 (match_operand:SI 3 "register_operand" " r")))]
|
|
759 "TARGET_ISA_V3 && optimize_size"
|
111
|
760 "and_slli\t%0, %3, %1, %2"
|
131
|
761 [(set_attr "type" "alu_shift")
|
|
762 (set_attr "length" "4")])
|
111
|
763
|
|
764 (define_insn "*and_srli"
|
131
|
765 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
766 (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
|
|
767 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
|
|
768 (match_operand:SI 3 "register_operand" " r")))]
|
|
769 "TARGET_ISA_V3 && optimize_size"
|
111
|
770 "and_srli\t%0, %3, %1, %2"
|
131
|
771 [(set_attr "type" "alu_shift")
|
|
772 (set_attr "length" "4")])
|
111
|
773
|
|
774
|
|
775 ;; ----------------------------------------------------------------------------
|
|
776 ;; 'OR' operation
|
|
777 ;; ----------------------------------------------------------------------------
|
|
778
|
|
779 ;; For V3/V3M ISA, we have 'or33' instruction.
|
|
780 ;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2.
|
131
|
781
|
|
782 (define_expand "iorsi3"
|
|
783 [(set (match_operand:SI 0 "register_operand" "")
|
|
784 (ior:SI (match_operand:SI 1 "register_operand" "")
|
|
785 (match_operand:SI 2 "general_operand" "")))]
|
111
|
786 ""
|
|
787 {
|
131
|
788 if (!nds32_ior_operand (operands[2], SImode))
|
|
789 operands[2] = force_reg (SImode, operands[2]);
|
|
790 })
|
111
|
791
|
131
|
792 (define_insn "*iorsi3"
|
|
793 [(set (match_operand:SI 0 "register_operand" "=l, r, r, r")
|
|
794 (ior:SI (match_operand:SI 1 "register_operand" "%0, r, r, r")
|
|
795 (match_operand:SI 2 "nds32_ior_operand" " l, r, Iu15, Ie15")))]
|
|
796 ""
|
|
797 "@
|
|
798 or33\t%0, %2
|
|
799 or\t%0, %1, %2
|
|
800 ori\t%0, %1, %2
|
|
801 bset\t%0, %1, %B2"
|
|
802 [(set_attr "type" "alu,alu,alu,alu")
|
|
803 (set_attr "length" " 2, 4, 4, 4")
|
|
804 (set_attr "feature" "v3m, v1, v1,pe1")])
|
111
|
805
|
|
806 (define_insn "*or_slli"
|
131
|
807 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
808 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
|
|
809 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
|
|
810 (match_operand:SI 3 "register_operand" " r")))]
|
|
811 "TARGET_ISA_V3 && optimize_size"
|
111
|
812 "or_slli\t%0, %3, %1, %2"
|
131
|
813 [(set_attr "type" "alu_shift")
|
|
814 (set_attr "length" "4")])
|
111
|
815
|
|
816 (define_insn "*or_srli"
|
131
|
817 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
818 (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
|
|
819 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
|
|
820 (match_operand:SI 3 "register_operand" " r")))]
|
|
821 "TARGET_ISA_V3 && optimize_size"
|
111
|
822 "or_srli\t%0, %3, %1, %2"
|
131
|
823 [(set_attr "type" "alu_shift")
|
|
824 (set_attr "length" "4")])
|
111
|
825
|
|
826
|
|
827 ;; ----------------------------------------------------------------------------
|
|
828 ;; 'XOR' operation
|
|
829 ;; ----------------------------------------------------------------------------
|
|
830
|
|
831 ;; For V3/V3M ISA, we have 'xor33' instruction.
|
|
832 ;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2.
|
131
|
833
|
|
834 (define_expand "xorsi3"
|
|
835 [(set (match_operand:SI 0 "register_operand" "")
|
|
836 (xor:SI (match_operand:SI 1 "register_operand" "")
|
|
837 (match_operand:SI 2 "general_operand" "")))]
|
111
|
838 ""
|
|
839 {
|
131
|
840 if (!nds32_xor_operand (operands[2], SImode))
|
|
841 operands[2] = force_reg (SImode, operands[2]);
|
|
842 })
|
111
|
843
|
131
|
844 (define_insn "*xorsi3"
|
|
845 [(set (match_operand:SI 0 "register_operand" "=l, r, r, r")
|
|
846 (xor:SI (match_operand:SI 1 "register_operand" "%0, r, r, r")
|
|
847 (match_operand:SI 2 "nds32_xor_operand" " l, r, Iu15, It15")))]
|
|
848 ""
|
|
849 "@
|
|
850 xor33\t%0, %2
|
|
851 xor\t%0, %1, %2
|
|
852 xori\t%0, %1, %2
|
|
853 btgl\t%0, %1, %B2"
|
|
854 [(set_attr "type" "alu,alu,alu,alu")
|
|
855 (set_attr "length" " 2, 4, 4, 4")
|
|
856 (set_attr "feature" "v3m, v1, v1,pe1")])
|
111
|
857
|
|
858 (define_insn "*xor_slli"
|
|
859 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
860 (xor:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
|
131
|
861 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
|
111
|
862 (match_operand:SI 3 "register_operand" " r")))]
|
131
|
863 "TARGET_ISA_V3 && optimize_size"
|
111
|
864 "xor_slli\t%0, %3, %1, %2"
|
131
|
865 [(set_attr "type" "alu_shift")
|
|
866 (set_attr "length" "4")])
|
111
|
867
|
|
868 (define_insn "*xor_srli"
|
131
|
869 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
870 (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
|
|
871 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
|
|
872 (match_operand:SI 3 "register_operand" " r")))]
|
|
873 "TARGET_ISA_V3 && optimize_size"
|
111
|
874 "xor_srli\t%0, %3, %1, %2"
|
131
|
875 [(set_attr "type" "alu_shift")
|
|
876 (set_attr "length" "4")])
|
111
|
877
|
|
878 ;; Rotate Right Instructions.
|
|
879
|
131
|
880 (define_insn "*rotrsi3"
|
|
881 [(set (match_operand:SI 0 "register_operand" "= r, r")
|
|
882 (rotatert:SI (match_operand:SI 1 "register_operand" " r, r")
|
|
883 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))]
|
111
|
884 ""
|
|
885 "@
|
131
|
886 rotri\t%0, %1, %2
|
|
887 rotr\t%0, %1, %2"
|
|
888 [(set_attr "type" " alu, alu")
|
|
889 (set_attr "subtype" "shift,shift")
|
|
890 (set_attr "length" " 4, 4")])
|
111
|
891
|
|
892
|
|
893 ;; ----------------------------------------------------------------------------
|
|
894 ;; 'NEG' operation
|
|
895 ;; ----------------------------------------------------------------------------
|
|
896
|
|
897 ;; For V3/V3M ISA, we have 'neg33' instruction.
|
|
898 ;; So we can identify 'xor Rt3,Ra3' case and set its length to be 2.
|
|
899 ;; And for V2 ISA, there is NO 'neg33' instruction.
|
|
900 ;; The only option is to use 'subri A,B,0' (its semantic is 'A = 0 - B').
|
|
901 (define_insn "negsi2"
|
131
|
902 [(set (match_operand:SI 0 "register_operand" "=l, r")
|
|
903 (neg:SI (match_operand:SI 1 "register_operand" " l, r")))]
|
111
|
904 ""
|
|
905 "@
|
|
906 neg33\t%0, %1
|
|
907 subri\t%0, %1, 0"
|
131
|
908 [(set_attr "type" "alu,alu")
|
|
909 (set_attr "length" " 2, 4")
|
|
910 (set_attr "feature" "v3m, v1")])
|
|
911
|
|
912 (define_expand "negsf2"
|
|
913 [(set (match_operand:SF 0 "register_operand" "")
|
|
914 (neg:SF (match_operand:SF 1 "register_operand" "")))]
|
|
915 ""
|
|
916 {
|
|
917 if (!TARGET_FPU_SINGLE && !TARGET_EXT_PERF)
|
|
918 {
|
|
919 rtx new_dst = simplify_gen_subreg (SImode, operands[0], SFmode, 0);
|
|
920 rtx new_src = simplify_gen_subreg (SImode, operands[1], SFmode, 0);
|
|
921
|
|
922 emit_insn (gen_xorsi3 (new_dst,
|
|
923 new_src,
|
|
924 gen_int_mode (0x80000000, SImode)));
|
|
925
|
|
926 DONE;
|
|
927 }
|
|
928 })
|
|
929
|
|
930 (define_expand "negdf2"
|
|
931 [(set (match_operand:DF 0 "register_operand" "")
|
|
932 (neg:DF (match_operand:DF 1 "register_operand" "")))]
|
|
933 ""
|
|
934 {
|
|
935 })
|
|
936
|
|
937 (define_insn_and_split "soft_negdf2"
|
|
938 [(set (match_operand:DF 0 "register_operand" "")
|
|
939 (neg:DF (match_operand:DF 1 "register_operand" "")))]
|
|
940 "!TARGET_FPU_DOUBLE"
|
|
941 "#"
|
|
942 "!TARGET_FPU_DOUBLE"
|
|
943 [(const_int 1)]
|
|
944 {
|
|
945 rtx src = operands[1];
|
|
946 rtx dst = operands[0];
|
|
947 rtx ori_dst = operands[0];
|
|
948
|
|
949 bool need_extra_move_for_dst_p;
|
|
950 /* FPU register can't change mode to SI directly, so we need create a
|
|
951 tmp register to handle it, and FPU register can't do `xor` or btgl. */
|
|
952 if (HARD_REGISTER_P (src)
|
|
953 && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (src)))
|
|
954 {
|
|
955 rtx tmp = gen_reg_rtx (DFmode);
|
|
956 emit_move_insn (tmp, src);
|
|
957 src = tmp;
|
|
958 }
|
|
959
|
|
960 if (HARD_REGISTER_P (dst)
|
|
961 && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (dst)))
|
|
962 {
|
|
963 need_extra_move_for_dst_p = true;
|
|
964 rtx tmp = gen_reg_rtx (DFmode);
|
|
965 dst = tmp;
|
|
966 }
|
|
967
|
|
968 rtx dst_high_part = simplify_gen_subreg (
|
|
969 SImode, dst,
|
|
970 DFmode, subreg_highpart_offset (SImode, DFmode));
|
|
971 rtx dst_low_part = simplify_gen_subreg (
|
|
972 SImode, dst,
|
|
973 DFmode, subreg_lowpart_offset (SImode, DFmode));
|
|
974 rtx src_high_part = simplify_gen_subreg (
|
|
975 SImode, src,
|
|
976 DFmode, subreg_highpart_offset (SImode, DFmode));
|
|
977 rtx src_low_part = simplify_gen_subreg (
|
|
978 SImode, src,
|
|
979 DFmode, subreg_lowpart_offset (SImode, DFmode));
|
|
980
|
|
981 emit_insn (gen_xorsi3 (dst_high_part,
|
|
982 src_high_part,
|
|
983 gen_int_mode (0x80000000, SImode)));
|
|
984 emit_move_insn (dst_low_part, src_low_part);
|
|
985
|
|
986 if (need_extra_move_for_dst_p)
|
|
987 emit_move_insn (ori_dst, dst);
|
|
988
|
|
989 DONE;
|
|
990 })
|
111
|
991
|
|
992
|
|
993 ;; ----------------------------------------------------------------------------
|
|
994 ;; 'ONE_COMPLIMENT' operation
|
|
995 ;; ----------------------------------------------------------------------------
|
|
996
|
|
997 ;; For V3/V3M ISA, we have 'not33' instruction.
|
|
998 ;; So we can identify 'not Rt3,Ra3' case and set its length to be 2.
|
|
999 (define_insn "one_cmplsi2"
|
|
1000 [(set (match_operand:SI 0 "register_operand" "=w, r")
|
|
1001 (not:SI (match_operand:SI 1 "register_operand" " w, r")))]
|
|
1002 ""
|
|
1003 "@
|
|
1004 not33\t%0, %1
|
|
1005 nor\t%0, %1, %1"
|
131
|
1006 [(set_attr "type" "alu,alu")
|
|
1007 (set_attr "length" " 2, 4")
|
|
1008 (set_attr "feature" "v3m, v1")])
|
111
|
1009
|
|
1010
|
|
1011 ;; ----------------------------------------------------------------------------
|
|
1012
|
|
1013 ;; Shift instructions.
|
|
1014
|
131
|
1015 (define_expand "<shift>si3"
|
|
1016 [(set (match_operand:SI 0 "register_operand" "")
|
|
1017 (shift_rotate:SI (match_operand:SI 1 "register_operand" "")
|
|
1018 (match_operand:SI 2 "nds32_rimm5u_operand" "")))]
|
111
|
1019 ""
|
131
|
1020 {
|
|
1021 if (operands[2] == const0_rtx)
|
|
1022 {
|
|
1023 emit_move_insn (operands[0], operands[1]);
|
|
1024 DONE;
|
|
1025 }
|
|
1026 })
|
111
|
1027
|
131
|
1028 (define_insn "*ashlsi3"
|
|
1029 [(set (match_operand:SI 0 "register_operand" "= l, r, r")
|
|
1030 (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r")
|
|
1031 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu03, Iu05, r")))]
|
111
|
1032 ""
|
|
1033 "@
|
131
|
1034 slli333\t%0, %1, %2
|
|
1035 slli\t%0, %1, %2
|
|
1036 sll\t%0, %1, %2"
|
|
1037 [(set_attr "type" " alu, alu, alu")
|
|
1038 (set_attr "subtype" "shift,shift,shift")
|
|
1039 (set_attr "length" " 2, 4, 4")])
|
111
|
1040
|
131
|
1041 (define_insn "*ashrsi3"
|
|
1042 [(set (match_operand:SI 0 "register_operand" "= d, r, r")
|
|
1043 (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r")
|
|
1044 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
|
111
|
1045 ""
|
|
1046 "@
|
131
|
1047 srai45\t%0, %2
|
|
1048 srai\t%0, %1, %2
|
|
1049 sra\t%0, %1, %2"
|
|
1050 [(set_attr "type" " alu, alu, alu")
|
|
1051 (set_attr "subtype" "shift,shift,shift")
|
|
1052 (set_attr "length" " 2, 4, 4")])
|
|
1053
|
|
1054 (define_insn "*lshrsi3"
|
|
1055 [(set (match_operand:SI 0 "register_operand" "= d, r, r")
|
|
1056 (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r")
|
|
1057 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
|
|
1058 ""
|
|
1059 "@
|
|
1060 srli45\t%0, %2
|
|
1061 srli\t%0, %1, %2
|
|
1062 srl\t%0, %1, %2"
|
|
1063 [(set_attr "type" " alu, alu, alu")
|
|
1064 (set_attr "subtype" "shift,shift,shift")
|
|
1065 (set_attr "length" " 2, 4, 4")])
|
111
|
1066
|
|
1067
|
|
1068 ;; ----------------------------------------------------------------------------
|
|
1069
|
|
1070 ;; ----------------------------------------------------------------------------
|
|
1071 ;; Conditional Move patterns
|
|
1072 ;; ----------------------------------------------------------------------------
|
|
1073
|
131
|
1074 (define_expand "mov<mode>cc"
|
|
1075 [(set (match_operand:QIHISI 0 "register_operand" "")
|
|
1076 (if_then_else:QIHISI (match_operand 1 "nds32_movecc_comparison_operator" "")
|
|
1077 (match_operand:QIHISI 2 "register_operand" "")
|
|
1078 (match_operand:QIHISI 3 "register_operand" "")))]
|
|
1079 "TARGET_CMOV && !optimize_size"
|
111
|
1080 {
|
131
|
1081 enum nds32_expand_result_type result = nds32_expand_movcc (operands);
|
|
1082 switch (result)
|
111
|
1083 {
|
131
|
1084 case EXPAND_DONE:
|
|
1085 DONE;
|
|
1086 break;
|
|
1087 case EXPAND_FAIL:
|
|
1088 FAIL;
|
|
1089 break;
|
|
1090 case EXPAND_CREATE_TEMPLATE:
|
|
1091 break;
|
|
1092 default:
|
|
1093 gcc_unreachable ();
|
111
|
1094 }
|
|
1095 })
|
|
1096
|
131
|
1097 (define_insn "cmovz<mode>"
|
|
1098 [(set (match_operand:QIHISI 0 "register_operand" "=r, r")
|
|
1099 (if_then_else:QIHISI (eq (match_operand:SI 1 "register_operand" " r, r")
|
111
|
1100 (const_int 0))
|
131
|
1101 (match_operand:QIHISI 2 "register_operand" " r, 0")
|
|
1102 (match_operand:QIHISI 3 "register_operand" " 0, r")))]
|
111
|
1103 "TARGET_CMOV"
|
|
1104 "@
|
|
1105 cmovz\t%0, %2, %1
|
|
1106 cmovn\t%0, %3, %1"
|
131
|
1107 [(set_attr "type" "alu")
|
111
|
1108 (set_attr "length" "4")])
|
|
1109
|
131
|
1110 (define_insn "cmovn<mode>"
|
|
1111 [(set (match_operand:QIHISI 0 "register_operand" "=r, r")
|
|
1112 (if_then_else:QIHISI (ne (match_operand:SI 1 "register_operand" " r, r")
|
111
|
1113 (const_int 0))
|
131
|
1114 (match_operand:QIHISI 2 "register_operand" " r, 0")
|
|
1115 (match_operand:QIHISI 3 "register_operand" " 0, r")))]
|
111
|
1116 "TARGET_CMOV"
|
|
1117 "@
|
|
1118 cmovn\t%0, %2, %1
|
|
1119 cmovz\t%0, %3, %1"
|
131
|
1120 [(set_attr "type" "alu")
|
111
|
1121 (set_attr "length" "4")])
|
|
1122
|
131
|
1123 ;; A hotfix to help RTL combiner to merge a cmovn insn and a zero_extend insn.
|
|
1124 ;; It should be removed once after we change the expansion form of the cmovn.
|
|
1125 (define_insn "*cmovn_simplified_<mode>"
|
|
1126 [(set (match_operand:QIHISI 0 "register_operand" "=r")
|
|
1127 (if_then_else:QIHISI (match_operand:SI 1 "register_operand" "r")
|
|
1128 (match_operand:QIHISI 2 "register_operand" "r")
|
|
1129 (match_operand:QIHISI 3 "register_operand" "0")))]
|
|
1130 ""
|
|
1131 "cmovn\t%0, %2, %1"
|
|
1132 [(set_attr "type" "alu")])
|
111
|
1133
|
|
1134 ;; ----------------------------------------------------------------------------
|
|
1135 ;; Conditional Branch patterns
|
|
1136 ;; ----------------------------------------------------------------------------
|
|
1137
|
|
1138 (define_expand "cbranchsi4"
|
|
1139 [(set (pc)
|
|
1140 (if_then_else (match_operator 0 "comparison_operator"
|
|
1141 [(match_operand:SI 1 "register_operand" "")
|
|
1142 (match_operand:SI 2 "nds32_reg_constant_operand" "")])
|
|
1143 (label_ref (match_operand 3 "" ""))
|
|
1144 (pc)))]
|
|
1145 ""
|
|
1146 {
|
131
|
1147 enum nds32_expand_result_type result = nds32_expand_cbranch (operands);
|
|
1148 switch (result)
|
111
|
1149 {
|
131
|
1150 case EXPAND_DONE:
|
111
|
1151 DONE;
|
131
|
1152 break;
|
|
1153 case EXPAND_FAIL:
|
|
1154 FAIL;
|
|
1155 break;
|
|
1156 case EXPAND_CREATE_TEMPLATE:
|
|
1157 break;
|
111
|
1158 default:
|
131
|
1159 gcc_unreachable ();
|
111
|
1160 }
|
|
1161 })
|
|
1162
|
|
1163
|
131
|
1164 (define_insn "cbranchsi4_equality_zero"
|
111
|
1165 [(set (pc)
|
|
1166 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
|
131
|
1167 [(match_operand:SI 1 "register_operand" "t,l, r")
|
111
|
1168 (const_int 0)])
|
|
1169 (label_ref (match_operand 2 "" ""))
|
|
1170 (pc)))]
|
|
1171 ""
|
|
1172 {
|
131
|
1173 return nds32_output_cbranchsi4_equality_zero (insn, operands);
|
111
|
1174 }
|
|
1175 [(set_attr "type" "branch")
|
131
|
1176 (set_attr_alternative "enabled"
|
|
1177 [
|
|
1178 ;; Alternative 0
|
|
1179 (if_then_else (match_test "TARGET_16_BIT")
|
|
1180 (const_string "yes")
|
|
1181 (const_string "no"))
|
|
1182 ;; Alternative 1
|
|
1183 (if_then_else (match_test "TARGET_16_BIT")
|
|
1184 (const_string "yes")
|
|
1185 (const_string "no"))
|
|
1186 ;; Alternative 2
|
|
1187 (const_string "yes")
|
|
1188 ])
|
111
|
1189 (set_attr_alternative "length"
|
|
1190 [
|
|
1191 ;; Alternative 0
|
131
|
1192 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1193 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
|
|
1194 (le (minus (match_dup 2) (pc)) (const_int 250)))
|
|
1195 (if_then_else (match_test "TARGET_16_BIT")
|
|
1196 (const_int 2)
|
|
1197 (const_int 4))
|
|
1198 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
|
|
1199 (le (minus (match_dup 2) (pc)) (const_int 65500)))
|
|
1200 (const_int 4)
|
|
1201 (if_then_else (match_test "TARGET_16_BIT")
|
|
1202 (const_int 8)
|
|
1203 (const_int 10))))
|
|
1204 (const_int 10))
|
|
1205 ;; Alternative 1
|
|
1206 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1207 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
|
|
1208 (le (minus (match_dup 2) (pc)) (const_int 250)))
|
|
1209 (if_then_else (match_test "TARGET_16_BIT")
|
|
1210 (const_int 2)
|
|
1211 (const_int 4))
|
|
1212 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
|
|
1213 (le (minus (match_dup 2) (pc)) (const_int 65500)))
|
|
1214 (const_int 4)
|
|
1215 (if_then_else (match_test "TARGET_16_BIT")
|
|
1216 (const_int 8)
|
|
1217 (const_int 10))))
|
|
1218 (const_int 10))
|
|
1219 ;; Alternative 2
|
|
1220 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
111
|
1221 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
|
|
1222 (le (minus (match_dup 2) (pc)) (const_int 65500)))
|
|
1223 (const_int 4)
|
131
|
1224 (const_int 10))
|
|
1225 (const_int 10))
|
111
|
1226 ])])
|
|
1227
|
|
1228
|
|
1229 ;; This pattern is dedicated to V2 ISA,
|
|
1230 ;; because V2 DOES NOT HAVE beqc/bnec instruction.
|
131
|
1231 (define_insn "cbranchsi4_equality_reg"
|
111
|
1232 [(set (pc)
|
|
1233 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
|
131
|
1234 [(match_operand:SI 1 "register_operand" "v, r")
|
|
1235 (match_operand:SI 2 "register_operand" "l, r")])
|
111
|
1236 (label_ref (match_operand 3 "" ""))
|
|
1237 (pc)))]
|
|
1238 "TARGET_ISA_V2"
|
|
1239 {
|
131
|
1240 return nds32_output_cbranchsi4_equality_reg (insn, operands);
|
111
|
1241 }
|
|
1242 [(set_attr "type" "branch")
|
131
|
1243 (set_attr_alternative "enabled"
|
|
1244 [
|
|
1245 ;; Alternative 0
|
|
1246 (if_then_else (match_test "TARGET_16_BIT")
|
|
1247 (const_string "yes")
|
|
1248 (const_string "no"))
|
|
1249 ;; Alternative 1
|
|
1250 (const_string "yes")
|
|
1251 ])
|
|
1252 (set_attr_alternative "length"
|
|
1253 [
|
|
1254 ;; Alternative 0
|
|
1255 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1256 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
|
|
1257 (le (minus (match_dup 3) (pc)) (const_int 250)))
|
|
1258 (const_int 2)
|
|
1259 (if_then_else (and (ge (minus (match_dup 3) (pc))
|
|
1260 (const_int -16350))
|
|
1261 (le (minus (match_dup 3) (pc))
|
|
1262 (const_int 16350)))
|
|
1263 (const_int 4)
|
|
1264 (const_int 8)))
|
|
1265 (const_int 8))
|
|
1266 ;; Alternative 1
|
|
1267 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1268 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
|
|
1269 (le (minus (match_dup 3) (pc)) (const_int 16350)))
|
|
1270 (const_int 4)
|
|
1271 (const_int 10))
|
|
1272 (const_int 10))
|
|
1273 ])])
|
111
|
1274
|
|
1275
|
|
1276 ;; This pattern is dedicated to V3/V3M,
|
|
1277 ;; because V3/V3M DO HAVE beqc/bnec instruction.
|
131
|
1278 (define_insn "cbranchsi4_equality_reg_or_const_int"
|
111
|
1279 [(set (pc)
|
|
1280 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
|
131
|
1281 [(match_operand:SI 1 "register_operand" "v, r, r")
|
|
1282 (match_operand:SI 2 "nds32_rimm11s_operand" "l, r, Is11")])
|
111
|
1283 (label_ref (match_operand 3 "" ""))
|
|
1284 (pc)))]
|
|
1285 "TARGET_ISA_V3 || TARGET_ISA_V3M"
|
|
1286 {
|
131
|
1287 return nds32_output_cbranchsi4_equality_reg_or_const_int (insn, operands);
|
111
|
1288 }
|
|
1289 [(set_attr "type" "branch")
|
131
|
1290 (set_attr_alternative "enabled"
|
|
1291 [
|
|
1292 ;; Alternative 0
|
|
1293 (if_then_else (match_test "TARGET_16_BIT")
|
|
1294 (const_string "yes")
|
|
1295 (const_string "no"))
|
|
1296 ;; Alternative 1
|
|
1297 (const_string "yes")
|
|
1298 ;; Alternative 2
|
|
1299 (const_string "yes")
|
|
1300 ])
|
111
|
1301 (set_attr_alternative "length"
|
|
1302 [
|
|
1303 ;; Alternative 0
|
131
|
1304 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1305 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
|
|
1306 (le (minus (match_dup 3) (pc)) (const_int 250)))
|
|
1307 (const_int 2)
|
|
1308 (if_then_else (and (ge (minus (match_dup 3) (pc))
|
|
1309 (const_int -16350))
|
|
1310 (le (minus (match_dup 3) (pc))
|
|
1311 (const_int 16350)))
|
|
1312 (const_int 4)
|
|
1313 (const_int 8)))
|
|
1314 (const_int 8))
|
111
|
1315 ;; Alternative 1
|
131
|
1316 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1317 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
|
|
1318 (le (minus (match_dup 3) (pc)) (const_int 16350)))
|
|
1319 (const_int 4)
|
|
1320 (const_int 10))
|
|
1321 (const_int 10))
|
|
1322 ;; Alternative 2
|
|
1323 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1324 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
|
|
1325 (le (minus (match_dup 3) (pc)) (const_int 250)))
|
|
1326 (const_int 4)
|
|
1327 (const_int 10))
|
|
1328 (const_int 10))
|
111
|
1329 ])])
|
|
1330
|
|
1331
|
|
1332 (define_insn "*cbranchsi4_greater_less_zero"
|
|
1333 [(set (pc)
|
|
1334 (if_then_else (match_operator 0 "nds32_greater_less_comparison_operator"
|
|
1335 [(match_operand:SI 1 "register_operand" "r")
|
|
1336 (const_int 0)])
|
|
1337 (label_ref (match_operand 2 "" ""))
|
|
1338 (pc)))]
|
|
1339 ""
|
|
1340 {
|
131
|
1341 return nds32_output_cbranchsi4_greater_less_zero (insn, operands);
|
111
|
1342 }
|
|
1343 [(set_attr "type" "branch")
|
|
1344 (set (attr "length")
|
131
|
1345 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1346 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
|
|
1347 (le (minus (match_dup 2) (pc)) (const_int 65500)))
|
|
1348 (const_int 4)
|
|
1349 (const_int 10))
|
|
1350 (const_int 10)))])
|
111
|
1351
|
|
1352
|
|
1353 (define_expand "cstoresi4"
|
|
1354 [(set (match_operand:SI 0 "register_operand" "")
|
|
1355 (match_operator:SI 1 "comparison_operator"
|
|
1356 [(match_operand:SI 2 "register_operand" "")
|
|
1357 (match_operand:SI 3 "nonmemory_operand" "")]))]
|
|
1358 ""
|
|
1359 {
|
131
|
1360 enum nds32_expand_result_type result = nds32_expand_cstore (operands);
|
|
1361 switch (result)
|
111
|
1362 {
|
131
|
1363 case EXPAND_DONE:
|
111
|
1364 DONE;
|
131
|
1365 break;
|
|
1366 case EXPAND_FAIL:
|
|
1367 FAIL;
|
|
1368 break;
|
|
1369 case EXPAND_CREATE_TEMPLATE:
|
|
1370 break;
|
111
|
1371 default:
|
|
1372 gcc_unreachable ();
|
|
1373 }
|
|
1374 })
|
|
1375
|
|
1376
|
131
|
1377 (define_expand "slts_compare"
|
|
1378 [(set (match_operand:SI 0 "register_operand" "")
|
|
1379 (lt:SI (match_operand:SI 1 "general_operand" "")
|
|
1380 (match_operand:SI 2 "general_operand" "")))]
|
|
1381 ""
|
|
1382 {
|
|
1383 if (!REG_P (operands[1]))
|
|
1384 operands[1] = force_reg (SImode, operands[1]);
|
|
1385
|
|
1386 if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2]))
|
|
1387 operands[2] = force_reg (SImode, operands[2]);
|
|
1388 })
|
|
1389
|
|
1390 (define_insn "slts_compare_impl"
|
|
1391 [(set (match_operand:SI 0 "register_operand" "=t, t, r, r")
|
|
1392 (lt:SI (match_operand:SI 1 "register_operand" " d, d, r, r")
|
|
1393 (match_operand:SI 2 "nds32_rimm15s_operand" " r,Iu05, r, Is15")))]
|
111
|
1394 ""
|
|
1395 "@
|
|
1396 slts45\t%1, %2
|
|
1397 sltsi45\t%1, %2
|
|
1398 slts\t%0, %1, %2
|
|
1399 sltsi\t%0, %1, %2"
|
131
|
1400 [(set_attr "type" "alu, alu, alu, alu")
|
|
1401 (set_attr "length" " 2, 2, 4, 4")])
|
|
1402
|
|
1403 (define_insn "slt_eq0"
|
|
1404 [(set (match_operand:SI 0 "register_operand" "=t, r")
|
|
1405 (eq:SI (match_operand:SI 1 "register_operand" " d, r")
|
|
1406 (const_int 0)))]
|
|
1407 ""
|
|
1408 "@
|
|
1409 slti45\t%1, 1
|
|
1410 slti\t%0, %1, 1"
|
|
1411 [(set_attr "type" "alu, alu")
|
|
1412 (set_attr "length" " 2, 4")])
|
111
|
1413
|
131
|
1414 (define_expand "slt_compare"
|
|
1415 [(set (match_operand:SI 0 "register_operand" "")
|
|
1416 (ltu:SI (match_operand:SI 1 "general_operand" "")
|
|
1417 (match_operand:SI 2 "general_operand" "")))]
|
|
1418 ""
|
|
1419 {
|
|
1420 if (!REG_P (operands[1]))
|
|
1421 operands[1] = force_reg (SImode, operands[1]);
|
|
1422
|
|
1423 if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2]))
|
|
1424 operands[2] = force_reg (SImode, operands[2]);
|
|
1425 })
|
|
1426
|
|
1427 (define_insn "slt_compare_impl"
|
|
1428 [(set (match_operand:SI 0 "register_operand" "=t, t, r, r")
|
|
1429 (ltu:SI (match_operand:SI 1 "register_operand" " d, d, r, r")
|
|
1430 (match_operand:SI 2 "nds32_rimm15s_operand" " r, Iu05, r, Is15")))]
|
111
|
1431 ""
|
|
1432 "@
|
|
1433 slt45\t%1, %2
|
|
1434 slti45\t%1, %2
|
|
1435 slt\t%0, %1, %2
|
|
1436 slti\t%0, %1, %2"
|
131
|
1437 [(set_attr "type" "alu, alu, alu, alu")
|
|
1438 (set_attr "length" " 2, 2, 4, 4")])
|
111
|
1439
|
|
1440
|
|
1441 ;; ----------------------------------------------------------------------------
|
|
1442
|
|
1443 ;; Unconditional and other jump instructions.
|
|
1444
|
|
1445 (define_insn "jump"
|
|
1446 [(set (pc) (label_ref (match_operand 0 "" "")))]
|
|
1447 ""
|
|
1448 {
|
|
1449 /* This unconditional jump has two forms:
|
|
1450 32-bit instruction => j imm24s << 1
|
|
1451 16-bit instruction => j8 imm8s << 1
|
|
1452
|
|
1453 For 32-bit case,
|
|
1454 we assume it is always reachable.
|
|
1455 For 16-bit case,
|
|
1456 it must satisfy { 255 >= (label - pc) >= -256 } condition.
|
|
1457 However, since the $pc for nds32 is at the beginning of the instruction,
|
|
1458 we should leave some length space for current insn.
|
|
1459 So we use range -250 ~ 250. */
|
|
1460 switch (get_attr_length (insn))
|
|
1461 {
|
|
1462 case 2:
|
|
1463 return "j8\t%0";
|
|
1464 case 4:
|
|
1465 return "j\t%0";
|
|
1466 default:
|
|
1467 gcc_unreachable ();
|
|
1468 }
|
|
1469 }
|
|
1470 [(set_attr "type" "branch")
|
131
|
1471 (set_attr "enabled" "yes")
|
111
|
1472 (set (attr "length")
|
131
|
1473 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
|
|
1474 (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250))
|
|
1475 (le (minus (match_dup 0) (pc)) (const_int 250)))
|
|
1476 (if_then_else (match_test "TARGET_16_BIT")
|
|
1477 (const_int 2)
|
|
1478 (const_int 4))
|
111
|
1479 (const_int 4))
|
|
1480 (const_int 4)))])
|
|
1481
|
|
1482 (define_insn "indirect_jump"
|
|
1483 [(set (pc) (match_operand:SI 0 "register_operand" "r, r"))]
|
|
1484 ""
|
|
1485 "@
|
131
|
1486 jr5\t%0
|
|
1487 jr\t%0"
|
111
|
1488 [(set_attr "type" "branch,branch")
|
|
1489 (set_attr "length" " 2, 4")])
|
|
1490
|
|
1491 ;; Subroutine call instruction returning no value.
|
|
1492 ;; operands[0]: It should be a mem RTX whose address is
|
|
1493 ;; the address of the function.
|
|
1494 ;; operands[1]: It is the number of bytes of arguments pushed as a const_int.
|
|
1495 ;; operands[2]: It is the number of registers used as operands.
|
|
1496
|
|
1497 (define_expand "call"
|
|
1498 [(parallel [(call (match_operand 0 "memory_operand" "")
|
|
1499 (match_operand 1))
|
|
1500 (clobber (reg:SI LP_REGNUM))
|
|
1501 (clobber (reg:SI TA_REGNUM))])]
|
|
1502 ""
|
131
|
1503 {
|
|
1504 rtx insn;
|
|
1505 rtx sym = XEXP (operands[0], 0);
|
|
1506
|
|
1507 if (TARGET_ICT_MODEL_LARGE
|
|
1508 && nds32_indirect_call_referenced_p (sym))
|
|
1509 {
|
|
1510 rtx reg = gen_reg_rtx (Pmode);
|
|
1511 emit_move_insn (reg, sym);
|
|
1512 operands[0] = gen_const_mem (Pmode, reg);
|
|
1513 }
|
|
1514
|
|
1515 if (flag_pic)
|
|
1516 {
|
|
1517 insn = emit_call_insn (gen_call_internal
|
|
1518 (XEXP (operands[0], 0), GEN_INT (0)));
|
|
1519 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
|
|
1520 DONE;
|
|
1521 }
|
|
1522 }
|
111
|
1523 )
|
|
1524
|
131
|
1525 (define_insn "call_internal"
|
|
1526 [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, S"))
|
111
|
1527 (match_operand 1))
|
|
1528 (clobber (reg:SI LP_REGNUM))
|
|
1529 (clobber (reg:SI TA_REGNUM))])]
|
|
1530 ""
|
|
1531 {
|
131
|
1532 rtx_insn *next_insn = next_active_insn (insn);
|
|
1533 bool align_p = (!(next_insn && get_attr_length (next_insn) == 2))
|
|
1534 && NDS32_ALIGN_P ();
|
|
1535 switch (which_alternative)
|
|
1536 {
|
|
1537 case 0:
|
|
1538 if (TARGET_16_BIT)
|
|
1539 {
|
|
1540 if (align_p)
|
|
1541 return "jral5\t%0\;.align 2";
|
|
1542 else
|
|
1543 return "jral5\t%0";
|
|
1544 }
|
|
1545 else
|
|
1546 {
|
|
1547 if (align_p)
|
|
1548 return "jral\t%0\;.align 2";
|
|
1549 else
|
|
1550 return "jral\t%0";
|
|
1551 }
|
|
1552 case 1:
|
|
1553 return nds32_output_call (insn, operands, operands[0],
|
|
1554 "bal\t%0", "jal\t%0", align_p);
|
|
1555 default:
|
|
1556 gcc_unreachable ();
|
|
1557 }
|
111
|
1558 }
|
131
|
1559 [(set_attr "enabled" "yes")
|
|
1560 (set_attr "type" "branch")
|
|
1561 (set_attr_alternative "length"
|
|
1562 [
|
|
1563 ;; Alternative 0
|
|
1564 (if_then_else (match_test "TARGET_16_BIT")
|
|
1565 (const_int 2)
|
|
1566 (const_int 4))
|
|
1567 ;; Alternative 1
|
|
1568 (if_then_else (match_test "flag_pic")
|
|
1569 (const_int 16)
|
|
1570 (if_then_else (match_test "nds32_long_call_p (operands[0])")
|
|
1571 (const_int 12)
|
|
1572 (const_int 4)))
|
|
1573 ])]
|
|
1574 )
|
111
|
1575
|
|
1576 ;; Subroutine call instruction returning a value.
|
|
1577 ;; operands[0]: It is the hard regiser in which the value is returned.
|
|
1578 ;; The rest three operands are the same as the
|
|
1579 ;; three operands of the 'call' instruction.
|
|
1580 ;; (but with numbers increased by one)
|
|
1581
|
|
1582 (define_expand "call_value"
|
|
1583 [(parallel [(set (match_operand 0)
|
|
1584 (call (match_operand 1 "memory_operand" "")
|
|
1585 (match_operand 2)))
|
|
1586 (clobber (reg:SI LP_REGNUM))
|
|
1587 (clobber (reg:SI TA_REGNUM))])]
|
|
1588 ""
|
131
|
1589 {
|
|
1590 rtx insn;
|
|
1591 rtx sym = XEXP (operands[1], 0);
|
|
1592
|
|
1593 if (TARGET_ICT_MODEL_LARGE
|
|
1594 && nds32_indirect_call_referenced_p (sym))
|
|
1595 {
|
|
1596 rtx reg = gen_reg_rtx (Pmode);
|
|
1597 emit_move_insn (reg, sym);
|
|
1598 operands[1] = gen_const_mem (Pmode, reg);
|
|
1599 }
|
|
1600
|
|
1601 if (flag_pic)
|
|
1602 {
|
|
1603 insn =
|
|
1604 emit_call_insn (gen_call_value_internal
|
|
1605 (operands[0], XEXP (operands[1], 0), GEN_INT (0)));
|
|
1606 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
|
|
1607 DONE;
|
|
1608 }
|
|
1609 }
|
111
|
1610 )
|
|
1611
|
131
|
1612 (define_insn "call_value_internal"
|
111
|
1613 [(parallel [(set (match_operand 0)
|
131
|
1614 (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, S"))
|
111
|
1615 (match_operand 2)))
|
|
1616 (clobber (reg:SI LP_REGNUM))
|
|
1617 (clobber (reg:SI TA_REGNUM))])]
|
|
1618 ""
|
131
|
1619 {
|
|
1620 rtx_insn *next_insn = next_active_insn (insn);
|
|
1621 bool align_p = (!(next_insn && get_attr_length (next_insn) == 2))
|
|
1622 && NDS32_ALIGN_P ();
|
|
1623 switch (which_alternative)
|
|
1624 {
|
|
1625 case 0:
|
|
1626 if (TARGET_16_BIT)
|
|
1627 {
|
|
1628 if (align_p)
|
|
1629 return "jral5\t%1\;.align 2";
|
|
1630 else
|
|
1631 return "jral5\t%1";
|
|
1632 }
|
|
1633 else
|
|
1634 {
|
|
1635 if (align_p)
|
|
1636 return "jral\t%1\;.align 2";
|
|
1637 else
|
|
1638 return "jral\t%1";
|
|
1639 }
|
|
1640 case 1:
|
|
1641 return nds32_output_call (insn, operands, operands[1],
|
|
1642 "bal\t%1", "jal\t%1", align_p);
|
|
1643 default:
|
|
1644 gcc_unreachable ();
|
|
1645 }
|
|
1646 }
|
|
1647 [(set_attr "enabled" "yes")
|
|
1648 (set_attr "type" "branch")
|
|
1649 (set_attr_alternative "length"
|
|
1650 [
|
|
1651 ;; Alternative 0
|
|
1652 (if_then_else (match_test "TARGET_16_BIT")
|
|
1653 (const_int 2)
|
|
1654 (const_int 4))
|
|
1655 ;; Alternative 1
|
|
1656 (if_then_else (match_test "flag_pic")
|
|
1657 (const_int 16)
|
|
1658 (if_then_else (match_test "nds32_long_call_p (operands[1])")
|
|
1659 (const_int 12)
|
|
1660 (const_int 4)))
|
|
1661 ])]
|
|
1662 )
|
111
|
1663
|
131
|
1664 ;; Call subroutine returning any type.
|
|
1665
|
|
1666 (define_expand "untyped_call"
|
|
1667 [(parallel [(call (match_operand 0 "" "")
|
|
1668 (const_int 0))
|
|
1669 (match_operand 1 "" "")
|
|
1670 (match_operand 2 "" "")])]
|
111
|
1671 ""
|
|
1672 {
|
131
|
1673 int i;
|
|
1674
|
|
1675 emit_call_insn (gen_call (operands[0], const0_rtx));
|
111
|
1676
|
131
|
1677 for (i = 0; i < XVECLEN (operands[2], 0); i++)
|
|
1678 {
|
|
1679 rtx set = XVECEXP (operands[2], 0, i);
|
|
1680 emit_move_insn (SET_DEST (set), SET_SRC (set));
|
|
1681 }
|
|
1682
|
|
1683 /* The optimizer does not know that the call sets the function value
|
|
1684 registers we stored in the result block. We avoid problems by
|
|
1685 claiming that all hard registers are used and clobbered at this
|
|
1686 point. */
|
|
1687 emit_insn (gen_blockage ());
|
|
1688 DONE;
|
|
1689 })
|
111
|
1690
|
|
1691 ;; ----------------------------------------------------------------------------
|
|
1692
|
|
1693 ;; The sibcall patterns.
|
|
1694
|
|
1695 ;; sibcall
|
131
|
1696 ;; sibcall_internal
|
111
|
1697
|
|
1698 (define_expand "sibcall"
|
|
1699 [(parallel [(call (match_operand 0 "memory_operand" "")
|
|
1700 (const_int 0))
|
|
1701 (clobber (reg:SI TA_REGNUM))
|
|
1702 (return)])]
|
|
1703 ""
|
131
|
1704 {
|
|
1705 rtx sym = XEXP (operands[0], 0);
|
111
|
1706
|
131
|
1707 if (TARGET_ICT_MODEL_LARGE
|
|
1708 && nds32_indirect_call_referenced_p (sym))
|
|
1709 {
|
|
1710 rtx reg = gen_reg_rtx (Pmode);
|
|
1711 emit_move_insn (reg, sym);
|
|
1712 operands[0] = gen_const_mem (Pmode, reg);
|
|
1713 }
|
|
1714 })
|
111
|
1715
|
131
|
1716 (define_insn "sibcall_internal"
|
|
1717 [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, S"))
|
111
|
1718 (match_operand 1))
|
|
1719 (clobber (reg:SI TA_REGNUM))
|
|
1720 (return)])]
|
|
1721 ""
|
|
1722 {
|
131
|
1723 switch (which_alternative)
|
|
1724 {
|
|
1725 case 0:
|
|
1726 if (TARGET_16_BIT)
|
|
1727 return "jr5\t%0";
|
|
1728 else
|
|
1729 return "jr\t%0";
|
|
1730 case 1:
|
|
1731 if (nds32_long_call_p (operands[0]))
|
|
1732 return "b\t%0";
|
|
1733 else
|
|
1734 return "j\t%0";
|
|
1735 default:
|
|
1736 gcc_unreachable ();
|
|
1737 }
|
111
|
1738 }
|
131
|
1739 [(set_attr "enabled" "yes")
|
|
1740 (set_attr "type" "branch")
|
|
1741 (set_attr_alternative "length"
|
|
1742 [
|
|
1743 ;; Alternative 0
|
|
1744 (if_then_else (match_test "TARGET_16_BIT")
|
|
1745 (const_int 2)
|
|
1746 (const_int 4))
|
|
1747 ;; Alternative 1
|
|
1748 (if_then_else (match_test "flag_pic")
|
|
1749 (const_int 16)
|
|
1750 (if_then_else (match_test "nds32_long_call_p (operands[0])")
|
|
1751 (const_int 12)
|
|
1752 (const_int 4)))
|
|
1753 ])]
|
|
1754 )
|
111
|
1755
|
|
1756 ;; sibcall_value
|
131
|
1757 ;; sibcall_value_internal
|
111
|
1758 ;; sibcall_value_immediate
|
|
1759
|
|
1760 (define_expand "sibcall_value"
|
|
1761 [(parallel [(set (match_operand 0)
|
|
1762 (call (match_operand 1 "memory_operand" "")
|
|
1763 (const_int 0)))
|
|
1764 (clobber (reg:SI TA_REGNUM))
|
|
1765 (return)])]
|
|
1766 ""
|
131
|
1767 {
|
|
1768 rtx sym = XEXP (operands[1], 0);
|
111
|
1769
|
131
|
1770 if (TARGET_ICT_MODEL_LARGE
|
|
1771 && nds32_indirect_call_referenced_p (sym))
|
|
1772 {
|
|
1773 rtx reg = gen_reg_rtx (Pmode);
|
|
1774 emit_move_insn (reg, sym);
|
|
1775 operands[1] = gen_const_mem (Pmode, reg);
|
|
1776 }
|
|
1777 })
|
|
1778
|
|
1779 (define_insn "sibcall_value_internal"
|
111
|
1780 [(parallel [(set (match_operand 0)
|
131
|
1781 (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, S"))
|
111
|
1782 (match_operand 2)))
|
|
1783 (clobber (reg:SI TA_REGNUM))
|
|
1784 (return)])]
|
|
1785 ""
|
|
1786 {
|
131
|
1787 switch (which_alternative)
|
|
1788 {
|
|
1789 case 0:
|
|
1790 if (TARGET_16_BIT)
|
|
1791 return "jr5\t%1";
|
|
1792 else
|
|
1793 return "jr\t%1";
|
|
1794 case 1:
|
|
1795 if (nds32_long_call_p (operands[1]))
|
|
1796 return "b\t%1";
|
|
1797 else
|
|
1798 return "j\t%1";
|
|
1799 default:
|
|
1800 gcc_unreachable ();
|
|
1801 }
|
111
|
1802 }
|
131
|
1803 [(set_attr "enabled" "yes")
|
|
1804 (set_attr "type" "branch")
|
|
1805 (set_attr_alternative "length"
|
|
1806 [
|
|
1807 ;; Alternative 0
|
|
1808 (if_then_else (match_test "TARGET_16_BIT")
|
|
1809 (const_int 2)
|
|
1810 (const_int 4))
|
|
1811 ;; Alternative 1
|
|
1812 (if_then_else (match_test "flag_pic")
|
|
1813 (const_int 16)
|
|
1814 (if_then_else (match_test "nds32_long_call_p (operands[1])")
|
|
1815 (const_int 12)
|
|
1816 (const_int 4)))
|
|
1817 ])]
|
|
1818 )
|
111
|
1819
|
|
1820 ;; ----------------------------------------------------------------------------
|
|
1821
|
|
1822 ;; prologue and epilogue.
|
|
1823
|
|
1824 (define_expand "prologue" [(const_int 0)]
|
|
1825 ""
|
|
1826 {
|
|
1827 /* Note that only under V3/V3M ISA, we could use v3push prologue.
|
131
|
1828 In addition, we need to check if v3push is indeed available. */
|
|
1829 if (NDS32_V3PUSH_AVAILABLE_P)
|
111
|
1830 nds32_expand_prologue_v3push ();
|
|
1831 else
|
|
1832 nds32_expand_prologue ();
|
131
|
1833
|
|
1834 /* If cfun->machine->fp_as_gp_p is true, we can generate special
|
|
1835 directive to guide linker doing fp-as-gp optimization.
|
|
1836 However, for a naked function, which means
|
|
1837 it should not have prologue/epilogue,
|
|
1838 using fp-as-gp still requires saving $fp by push/pop behavior and
|
|
1839 there is no benefit to use fp-as-gp on such small function.
|
|
1840 So we need to make sure this function is NOT naked as well. */
|
|
1841 if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p)
|
|
1842 emit_insn (gen_omit_fp_begin (gen_rtx_REG (SImode, FP_REGNUM)));
|
|
1843
|
111
|
1844 DONE;
|
|
1845 })
|
|
1846
|
|
1847 (define_expand "epilogue" [(const_int 0)]
|
|
1848 ""
|
|
1849 {
|
131
|
1850 /* If cfun->machine->fp_as_gp_p is true, we can generate special
|
|
1851 directive to guide linker doing fp-as-gp optimization.
|
|
1852 However, for a naked function, which means
|
|
1853 it should not have prologue/epilogue,
|
|
1854 using fp-as-gp still requires saving $fp by push/pop behavior and
|
|
1855 there is no benefit to use fp-as-gp on such small function.
|
|
1856 So we need to make sure this function is NOT naked as well. */
|
|
1857 if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p)
|
|
1858 emit_insn (gen_omit_fp_end (gen_rtx_REG (SImode, FP_REGNUM)));
|
|
1859
|
111
|
1860 /* Note that only under V3/V3M ISA, we could use v3pop epilogue.
|
131
|
1861 In addition, we need to check if v3push is indeed available. */
|
|
1862 if (NDS32_V3PUSH_AVAILABLE_P)
|
111
|
1863 nds32_expand_epilogue_v3pop (false);
|
|
1864 else
|
|
1865 nds32_expand_epilogue (false);
|
|
1866 DONE;
|
|
1867 })
|
|
1868
|
|
1869 (define_expand "sibcall_epilogue" [(const_int 0)]
|
|
1870 ""
|
|
1871 {
|
|
1872 /* Pass true to indicate that this is sibcall epilogue and
|
|
1873 exit from a function without the final branch back to the
|
|
1874 calling function. */
|
131
|
1875 nds32_expand_epilogue (true);
|
111
|
1876
|
|
1877 DONE;
|
|
1878 })
|
|
1879
|
|
1880
|
|
1881 ;; nop instruction.
|
|
1882
|
|
1883 (define_insn "nop"
|
|
1884 [(const_int 0)]
|
|
1885 ""
|
|
1886 {
|
|
1887 if (TARGET_16_BIT)
|
|
1888 return "nop16";
|
|
1889 else
|
|
1890 return "nop";
|
|
1891 }
|
|
1892 [(set_attr "type" "misc")
|
131
|
1893 (set_attr "enabled" "yes")
|
111
|
1894 (set (attr "length")
|
|
1895 (if_then_else (match_test "TARGET_16_BIT")
|
|
1896 (const_int 2)
|
|
1897 (const_int 4)))])
|
|
1898
|
|
1899
|
|
1900 ;; ----------------------------------------------------------------------------
|
|
1901 ;; Stack push/pop operations
|
|
1902 ;; ----------------------------------------------------------------------------
|
|
1903
|
|
1904 ;; The pattern for stack push.
|
|
1905 ;; Both stack_push_multiple and stack_v3push use the following pattern.
|
|
1906 ;; So we need to use TARGET_V3PUSH to determine the instruction length.
|
|
1907 (define_insn "*stack_push"
|
|
1908 [(match_parallel 0 "nds32_stack_push_operation"
|
|
1909 [(set (mem:SI (plus:SI (reg:SI SP_REGNUM)
|
|
1910 (match_operand:SI 1 "const_int_operand" "")))
|
|
1911 (match_operand:SI 2 "register_operand" ""))
|
|
1912 ])]
|
|
1913 ""
|
|
1914 {
|
|
1915 return nds32_output_stack_push (operands[0]);
|
|
1916 }
|
131
|
1917 [(set_attr "type" "store_multiple")
|
|
1918 (set_attr "combo" "12")
|
|
1919 (set_attr "enabled" "yes")
|
111
|
1920 (set (attr "length")
|
131
|
1921 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
|
111
|
1922 (const_int 2)
|
|
1923 (const_int 4)))])
|
|
1924
|
|
1925
|
|
1926 ;; The pattern for stack pop.
|
|
1927 ;; Both stack_pop_multiple and stack_v3pop use the following pattern.
|
|
1928 ;; So we need to use TARGET_V3PUSH to determine the instruction length.
|
|
1929 (define_insn "*stack_pop"
|
|
1930 [(match_parallel 0 "nds32_stack_pop_operation"
|
|
1931 [(set (match_operand:SI 1 "register_operand" "")
|
|
1932 (mem:SI (reg:SI SP_REGNUM)))
|
|
1933 ])]
|
|
1934 ""
|
|
1935 {
|
|
1936 return nds32_output_stack_pop (operands[0]);
|
|
1937 }
|
131
|
1938 [(set_attr "type" "load_multiple")
|
|
1939 (set_attr "combo" "12")
|
|
1940 (set_attr "enabled" "yes")
|
111
|
1941 (set (attr "length")
|
131
|
1942 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
|
111
|
1943 (const_int 2)
|
|
1944 (const_int 4)))])
|
|
1945
|
|
1946
|
|
1947 ;; ----------------------------------------------------------------------------
|
|
1948 ;; Return operation patterns
|
|
1949 ;; ----------------------------------------------------------------------------
|
|
1950
|
|
1951 ;; Use this pattern to expand a return instruction
|
|
1952 ;; with simple_return rtx if no epilogue is required.
|
|
1953 (define_expand "return"
|
131
|
1954 [(parallel [(return)
|
|
1955 (clobber (reg:SI FP_REGNUM))])]
|
|
1956 "nds32_can_use_return_insn ()"
|
|
1957 {
|
|
1958 /* Emit as the simple return. */
|
|
1959 if (!cfun->machine->fp_as_gp_p
|
|
1960 && cfun->machine->naked_p
|
|
1961 && (cfun->machine->va_args_size == 0))
|
|
1962 {
|
|
1963 emit_jump_insn (gen_return_internal ());
|
|
1964 DONE;
|
|
1965 }
|
|
1966 })
|
|
1967
|
|
1968 ;; This pattern is expanded only by the shrink-wrapping optimization
|
|
1969 ;; on paths where the function prologue has not been executed.
|
|
1970 ;; However, such optimization may reorder the prologue/epilogue blocks
|
|
1971 ;; together with basic blocks within function body.
|
|
1972 ;; So we must disable this pattern if we have already decided
|
|
1973 ;; to perform fp_as_gp optimization, which requires prologue to be
|
|
1974 ;; first block and epilogue to be last block.
|
|
1975 (define_expand "simple_return"
|
111
|
1976 [(simple_return)]
|
131
|
1977 "!cfun->machine->fp_as_gp_p"
|
111
|
1978 ""
|
|
1979 )
|
|
1980
|
131
|
1981 (define_insn "*nds32_return"
|
|
1982 [(parallel [(return)
|
|
1983 (clobber (reg:SI FP_REGNUM))])]
|
111
|
1984 ""
|
131
|
1985 {
|
|
1986 return nds32_output_return ();
|
|
1987 }
|
|
1988 [(set_attr "type" "branch")
|
|
1989 (set_attr "enabled" "yes")
|
|
1990 (set_attr "length" "4")])
|
111
|
1991
|
|
1992 (define_insn "return_internal"
|
|
1993 [(simple_return)]
|
|
1994 ""
|
|
1995 {
|
131
|
1996 if (nds32_isr_function_critical_p (current_function_decl))
|
|
1997 return "iret";
|
|
1998
|
111
|
1999 if (TARGET_16_BIT)
|
|
2000 return "ret5";
|
|
2001 else
|
|
2002 return "ret";
|
|
2003 }
|
|
2004 [(set_attr "type" "branch")
|
131
|
2005 (set_attr "enabled" "yes")
|
111
|
2006 (set (attr "length")
|
131
|
2007 (if_then_else (match_test "nds32_isr_function_critical_p (current_function_decl)")
|
|
2008 (const_int 4)
|
|
2009 (if_then_else (match_test "TARGET_16_BIT")
|
|
2010 (const_int 2)
|
|
2011 (const_int 4))))])
|
111
|
2012
|
|
2013
|
|
2014 ;; ----------------------------------------------------------------------------
|
|
2015 ;; Jump Table patterns
|
|
2016 ;; ----------------------------------------------------------------------------
|
|
2017 ;; Need to implement ASM_OUTPUT_ADDR_VEC_ELT (for normal jump table)
|
|
2018 ;; or ASM_OUTPUT_ADDR_DIFF_ELT (for pc relative jump table) as well.
|
|
2019 ;;
|
|
2020 ;; operands[0]: The index to dispatch on.
|
|
2021 ;; operands[1]: The lower bound for indices in the table.
|
|
2022 ;; operands[2]: The total range of indices int the table.
|
|
2023 ;; i.e. The largest index minus the smallest one.
|
|
2024 ;; operands[3]: A label that precedes the table itself.
|
|
2025 ;; operands[4]: A label to jump to if the index has a value outside the bounds.
|
|
2026 ;;
|
|
2027 ;; We need to create following sequences for jump table code generation:
|
|
2028 ;; A) k <-- (plus (operands[0]) (-operands[1]))
|
|
2029 ;; B) if (gtu k operands[2]) then goto operands[4]
|
|
2030 ;; C) t <-- operands[3]
|
|
2031 ;; D) z <-- (mem (plus (k << 0 or 1 or 2) t))
|
|
2032 ;; E) z <-- t + z (NOTE: This is only required for pc relative jump table.)
|
|
2033 ;; F) jump to target with register t or z
|
|
2034 ;;
|
|
2035 ;; The steps C, D, E, and F are performed by casesi_internal pattern.
|
|
2036 (define_expand "casesi"
|
|
2037 [(match_operand:SI 0 "register_operand" "r") ; index to jump on
|
|
2038 (match_operand:SI 1 "immediate_operand" "i") ; lower bound
|
|
2039 (match_operand:SI 2 "immediate_operand" "i") ; total range
|
|
2040 (match_operand:SI 3 "" "") ; table label
|
|
2041 (match_operand:SI 4 "" "")] ; Out of range label
|
|
2042 ""
|
|
2043 {
|
|
2044 rtx add_tmp;
|
|
2045 rtx reg, test;
|
131
|
2046 rtx tmp_reg;
|
111
|
2047
|
|
2048 /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */
|
|
2049 if (operands[1] != const0_rtx)
|
|
2050 {
|
|
2051 reg = gen_reg_rtx (SImode);
|
|
2052 add_tmp = gen_int_mode (-INTVAL (operands[1]), SImode);
|
|
2053
|
|
2054 /* If the integer value is not in the range of imm15s,
|
|
2055 we need to force register first because our addsi3 pattern
|
|
2056 only accept nds32_rimm15s_operand predicate. */
|
|
2057 add_tmp = force_reg (SImode, add_tmp);
|
|
2058
|
|
2059 emit_insn (gen_addsi3 (reg, operands[0], add_tmp));
|
|
2060 operands[0] = reg;
|
|
2061 }
|
|
2062
|
|
2063 /* Step B: "if (gtu k operands[2]) then goto operands[4]". */
|
|
2064 test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]);
|
|
2065 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2],
|
|
2066 operands[4]));
|
|
2067
|
131
|
2068 tmp_reg = gen_reg_rtx (SImode);
|
|
2069 /* Step C, D, E, and F, using another temporary register tmp_reg. */
|
|
2070 if (flag_pic)
|
|
2071 emit_use (pic_offset_table_rtx);
|
|
2072
|
|
2073 emit_jump_insn (gen_casesi_internal (operands[0],
|
|
2074 operands[3],
|
|
2075 tmp_reg));
|
111
|
2076 DONE;
|
|
2077 })
|
|
2078
|
|
2079 ;; We are receiving operands from casesi pattern:
|
|
2080 ;;
|
|
2081 ;; operands[0]: The index that have been substracted with lower bound.
|
|
2082 ;; operands[1]: A label that precedes the table itself.
|
|
2083 ;; operands[2]: A temporary register to retrieve value in table.
|
|
2084 ;;
|
|
2085 ;; We need to perform steps C, D, E, and F:
|
|
2086 ;;
|
|
2087 ;; C) t <-- operands[1]
|
|
2088 ;; D) z <-- (mem (plus (operands[0] << m) t))
|
|
2089 ;; m is 2 for normal jump table.
|
|
2090 ;; m is 0, 1, or 2 for pc relative jump table based on diff size.
|
|
2091 ;; E) t <-- z + t (NOTE: This is only required for pc relative jump table.)
|
|
2092 ;; F) Jump to target with register t or z.
|
|
2093 ;;
|
|
2094 ;; The USE in this pattern is needed to tell flow analysis that this is
|
|
2095 ;; a CASESI insn. It has no other purpose.
|
|
2096 (define_insn "casesi_internal"
|
|
2097 [(parallel [(set (pc)
|
|
2098 (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
|
|
2099 (const_int 4))
|
|
2100 (label_ref (match_operand 1 "" "")))))
|
|
2101 (use (label_ref (match_dup 1)))
|
|
2102 (clobber (match_operand:SI 2 "register_operand" "=r"))
|
|
2103 (clobber (reg:SI TA_REGNUM))])]
|
|
2104 ""
|
|
2105 {
|
|
2106 if (CASE_VECTOR_PC_RELATIVE)
|
|
2107 return nds32_output_casesi_pc_relative (operands);
|
|
2108 else
|
|
2109 return nds32_output_casesi (operands);
|
|
2110 }
|
131
|
2111 [(set_attr "type" "branch")
|
|
2112 (set (attr "length")
|
|
2113 (if_then_else (match_test "flag_pic")
|
|
2114 (const_int 28)
|
|
2115 (const_int 20)))])
|
111
|
2116
|
|
2117 ;; ----------------------------------------------------------------------------
|
|
2118
|
|
2119 ;; Performance Extension
|
|
2120
|
131
|
2121 ; If -fwrapv option is issued, GCC expects there will be
|
|
2122 ; signed overflow situation. So the ABS(INT_MIN) is still INT_MIN
|
|
2123 ; (e.g. ABS(0x80000000)=0x80000000).
|
|
2124 ; However, the hardware ABS instruction of nds32 target
|
|
2125 ; always performs saturation: abs 0x80000000 -> 0x7fffffff.
|
|
2126 ; So that we can only enable abssi2 pattern if flag_wrapv is NOT presented.
|
|
2127 (define_insn "abssi2"
|
|
2128 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2129 (abs:SI (match_operand:SI 1 "register_operand" " r")))]
|
|
2130 "TARGET_EXT_PERF && TARGET_HW_ABS && !flag_wrapv"
|
|
2131 "abs\t%0, %1"
|
|
2132 [(set_attr "type" "alu")
|
|
2133 (set_attr "length" "4")])
|
|
2134
|
111
|
2135 (define_insn "clzsi2"
|
|
2136 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2137 (clz:SI (match_operand:SI 1 "register_operand" " r")))]
|
131
|
2138 "TARGET_EXT_PERF"
|
111
|
2139 "clz\t%0, %1"
|
|
2140 [(set_attr "type" "alu")
|
|
2141 (set_attr "length" "4")])
|
|
2142
|
|
2143 (define_insn "smaxsi3"
|
|
2144 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2145 (smax:SI (match_operand:SI 1 "register_operand" " r")
|
|
2146 (match_operand:SI 2 "register_operand" " r")))]
|
131
|
2147 "TARGET_EXT_PERF"
|
111
|
2148 "max\t%0, %1, %2"
|
|
2149 [(set_attr "type" "alu")
|
|
2150 (set_attr "length" "4")])
|
|
2151
|
|
2152 (define_insn "sminsi3"
|
|
2153 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2154 (smin:SI (match_operand:SI 1 "register_operand" " r")
|
|
2155 (match_operand:SI 2 "register_operand" " r")))]
|
131
|
2156 "TARGET_EXT_PERF"
|
111
|
2157 "min\t%0, %1, %2"
|
|
2158 [(set_attr "type" "alu")
|
|
2159 (set_attr "length" "4")])
|
|
2160
|
131
|
2161 (define_insn "btst"
|
|
2162 [(set (match_operand:SI 0 "register_operand" "= r")
|
|
2163 (zero_extract:SI (match_operand:SI 1 "register_operand" " r")
|
111
|
2164 (const_int 1)
|
131
|
2165 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")))]
|
|
2166 "TARGET_EXT_PERF"
|
111
|
2167 "btst\t%0, %1, %2"
|
|
2168 [(set_attr "type" "alu")
|
|
2169 (set_attr "length" "4")])
|
|
2170
|
131
|
2171 (define_insn "ave"
|
|
2172 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2173 (truncate:SI
|
|
2174 (ashiftrt:DI
|
|
2175 (plus:DI
|
|
2176 (plus:DI
|
|
2177 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
|
|
2178 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
|
|
2179 (const_int 1))
|
|
2180 (const_int 1))))]
|
|
2181 "TARGET_EXT_PERF"
|
|
2182 "ave\t%0, %1, %2"
|
|
2183 [(set_attr "type" "alu")
|
|
2184 (set_attr "length" "4")])
|
|
2185
|
111
|
2186 ;; ----------------------------------------------------------------------------
|
|
2187
|
|
2188 ;; Pseudo NOPs
|
|
2189
|
131
|
2190 (define_insn "relax_group"
|
|
2191 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)]
|
|
2192 ""
|
|
2193 ".relax_hint %0"
|
|
2194 [(set_attr "length" "0")]
|
|
2195 )
|
|
2196
|
|
2197 ;; Output .omit_fp_begin for fp-as-gp optimization.
|
|
2198 ;; Also we have to set $fp register.
|
|
2199 (define_insn "omit_fp_begin"
|
|
2200 [(set (match_operand:SI 0 "register_operand" "=x")
|
|
2201 (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_OMIT_FP_BEGIN))]
|
|
2202 ""
|
|
2203 "! -----\;.omit_fp_begin\;la\t$fp,_FP_BASE_\;! -----"
|
|
2204 [(set_attr "length" "8")]
|
|
2205 )
|
|
2206
|
|
2207 ;; Output .omit_fp_end for fp-as-gp optimization.
|
|
2208 ;; Claim that we have to use $fp register.
|
|
2209 (define_insn "omit_fp_end"
|
|
2210 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "x")] UNSPEC_VOLATILE_OMIT_FP_END)]
|
|
2211 ""
|
|
2212 "! -----\;.omit_fp_end\;! -----"
|
|
2213 [(set_attr "length" "0")]
|
|
2214 )
|
|
2215
|
111
|
2216 (define_insn "pop25return"
|
|
2217 [(return)
|
|
2218 (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_POP25_RETURN)]
|
|
2219 ""
|
|
2220 "! return for pop 25"
|
|
2221 [(set_attr "length" "0")]
|
|
2222 )
|
|
2223
|
131
|
2224 ;; Add pc
|
|
2225 (define_insn "add_pc"
|
|
2226 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2227 (plus:SI (match_operand:SI 1 "register_operand" "0")
|
|
2228 (pc)))]
|
|
2229 "TARGET_LINUX_ABI || flag_pic"
|
|
2230 "add5.pc\t%0"
|
|
2231 [(set_attr "type" "alu")
|
|
2232 (set_attr "length" "4")]
|
|
2233 )
|
|
2234
|
|
2235 (define_expand "bswapsi2"
|
|
2236 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2237 (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
|
|
2238 ""
|
|
2239 {
|
|
2240 emit_insn (gen_unspec_wsbh (operands[0], operands[1]));
|
|
2241 emit_insn (gen_rotrsi3 (operands[0], operands[0], GEN_INT (16)));
|
|
2242 DONE;
|
|
2243 })
|
|
2244
|
|
2245 (define_insn "bswaphi2"
|
|
2246 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
2247 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
|
|
2248 ""
|
|
2249 "wsbh\t%0, %1"
|
|
2250 [(set_attr "type" "alu")
|
|
2251 (set_attr "length" "4")]
|
|
2252 )
|
|
2253
|
111
|
2254 ;; ----------------------------------------------------------------------------
|
131
|
2255
|
|
2256 ;; Patterns for exception handling
|
|
2257
|
|
2258 (define_expand "eh_return"
|
|
2259 [(use (match_operand 0 "general_operand"))]
|
|
2260 ""
|
|
2261 {
|
|
2262 emit_insn (gen_nds32_eh_return (operands[0]));
|
|
2263 DONE;
|
|
2264 })
|
|
2265
|
|
2266 (define_insn_and_split "nds32_eh_return"
|
|
2267 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_EH_RETURN)]
|
|
2268 ""
|
|
2269 "#"
|
|
2270 "reload_completed"
|
|
2271 [(const_int 0)]
|
|
2272 {
|
|
2273 rtx place;
|
|
2274 rtx addr;
|
|
2275
|
|
2276 /* The operands[0] is the handler address. We need to assign it
|
|
2277 to return address rtx so that we can jump to exception handler
|
|
2278 when returning from current function. */
|
|
2279
|
|
2280 if (cfun->machine->lp_size == 0)
|
|
2281 {
|
|
2282 /* If $lp is not saved in the stack frame, we can take $lp directly. */
|
|
2283 place = gen_rtx_REG (SImode, LP_REGNUM);
|
|
2284 }
|
|
2285 else
|
|
2286 {
|
|
2287 /* Otherwise, we need to locate the stack slot of return address.
|
|
2288 The return address is generally saved in [$fp-4] location.
|
|
2289 However, DSE (dead store elimination) does not detect an alias
|
|
2290 between [$fp-x] and [$sp+y]. This can result in a store to save
|
|
2291 $lp introduced by builtin_eh_return() being incorrectly deleted
|
|
2292 if it is based on $fp. The solution we take here is to compute
|
|
2293 the offset relative to stack pointer and then use $sp to access
|
|
2294 location so that the alias can be detected.
|
|
2295 FIXME: What if the immediate value "offset" is too large to be
|
|
2296 fit in a single addi instruction? */
|
|
2297 HOST_WIDE_INT offset;
|
|
2298
|
|
2299 offset = (cfun->machine->fp_size
|
|
2300 + cfun->machine->gp_size
|
|
2301 + cfun->machine->lp_size
|
|
2302 + cfun->machine->callee_saved_gpr_regs_size
|
|
2303 + cfun->machine->callee_saved_area_gpr_padding_bytes
|
|
2304 + cfun->machine->callee_saved_fpr_regs_size
|
|
2305 + cfun->machine->eh_return_data_regs_size
|
|
2306 + cfun->machine->local_size
|
|
2307 + cfun->machine->out_args_size);
|
|
2308
|
|
2309 addr = plus_constant (Pmode, stack_pointer_rtx, offset - 4);
|
|
2310 place = gen_frame_mem (SImode, addr);
|
|
2311 }
|
|
2312
|
|
2313 emit_move_insn (place, operands[0]);
|
|
2314 DONE;
|
|
2315 })
|
|
2316
|
|
2317 ;; ----------------------------------------------------------------------------
|
|
2318
|
|
2319 ;; Patterns for TLS.
|
|
2320 ;; The following two tls patterns don't be expanded directly because the
|
|
2321 ;; intermediate value may be spilled into the stack. As a result, it is
|
|
2322 ;; hard to analyze the define-use chain in the relax_opt pass.
|
|
2323
|
|
2324
|
|
2325 ;; There is a unspec operand to record RELAX_GROUP number because each
|
|
2326 ;; emitted instruction need a relax_hint above it.
|
|
2327 (define_insn "tls_desc"
|
|
2328 [(set (reg:SI 0)
|
|
2329 (call (unspec_volatile:SI [(match_operand:SI 0 "nds32_symbolic_operand" "i")] UNSPEC_TLS_DESC)
|
|
2330 (const_int 1)))
|
|
2331 (use (unspec [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))
|
|
2332 (use (reg:SI GP_REGNUM))
|
|
2333 (clobber (reg:SI LP_REGNUM))
|
|
2334 (clobber (reg:SI TA_REGNUM))]
|
|
2335 ""
|
|
2336 {
|
|
2337 return nds32_output_tls_desc (operands);
|
|
2338 }
|
|
2339 [(set_attr "length" "20")
|
|
2340 (set_attr "type" "branch")]
|
|
2341 )
|
|
2342
|
|
2343 ;; There is a unspec operand to record RELAX_GROUP number because each
|
|
2344 ;; emitted instruction need a relax_hint above it.
|
|
2345 (define_insn "tls_ie"
|
|
2346 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2347 (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE))
|
|
2348 (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))
|
|
2349 (use (reg:SI GP_REGNUM))]
|
|
2350 ""
|
|
2351 {
|
|
2352 return nds32_output_tls_ie (operands);
|
|
2353 }
|
|
2354 [(set (attr "length") (if_then_else (match_test "flag_pic")
|
|
2355 (const_int 12)
|
|
2356 (const_int 8)))
|
|
2357 (set_attr "type" "misc")]
|
|
2358 )
|
|
2359
|
|
2360 ;; The pattern is for some relaxation groups that have to keep addsi3 in 32-bit mode.
|
|
2361 (define_insn "addsi3_32bit"
|
|
2362 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2363 (unspec:SI [(match_operand:SI 1 "register_operand" "%r")
|
|
2364 (match_operand:SI 2 "register_operand" " r")] UNSPEC_ADD32))]
|
|
2365 ""
|
|
2366 "add\t%0, %1, %2";
|
|
2367 [(set_attr "type" "alu")
|
|
2368 (set_attr "length" "4")
|
|
2369 (set_attr "feature" "v1")])
|
|
2370
|
|
2371 ;; ----------------------------------------------------------------------------
|