]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nds32/nds32.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / nds32 / nds32.md
1 ;; Machine description of Andes NDS32 cpu for GNU compiler
2 ;; Copyright (C) 2012-2019 Free Software Foundation, Inc.
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
49 ;; Include floating-point patterns.
50 (include "nds32-fpu.md")
51
52 ;; Include peephole patterns.
53 (include "nds32-peephole2.md")
54
55
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
72 ;; Insn type, it is used to default other attribute values.
73 (define_attr "type"
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"
77 (const_string "unknown"))
78
79 ;; Insn sub-type
80 (define_attr "subtype"
81 "simple,shift,saturation"
82 (const_string "simple"))
83
84 ;; Length, in bytes, default is 4-bytes.
85 (define_attr "length" "" (const_int 4))
86
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"))
103
104 ;; Enabled, which is used to enable/disable insn alternatives.
105 ;; Note that we use length and TARGET_16_BIT here as criteria.
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"))))
137
138
139 ;; ----------------------------------------------------------------------------
140
141 (include "nds32-dspext.md")
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
148 (define_expand "mov<mode>"
149 [(set (match_operand:QIHI 0 "general_operand" "")
150 (match_operand:QIHI 1 "general_operand" ""))]
151 ""
152 {
153 /* Need to force register if mem <- !reg. */
154 if (MEM_P (operands[0]) && !REG_P (operands[1]))
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 }
164 })
165
166 (define_expand "movmisalign<mode>"
167 [(set (match_operand:SIDI 0 "general_operand" "")
168 (match_operand:SIDI 1 "general_operand" ""))]
169 ""
170 {
171 rtx addr;
172 if (MEM_P (operands[0]) && !REG_P (operands[1]))
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;
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 }
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 }
239 })
240
241 (define_insn "*mov<mode>"
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)"
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:
264 case 11:
265 return nds32_output_16bit_load (operands, <byte>);
266 case 12:
267 return nds32_output_32bit_load (operands, <byte>);
268 case 13:
269 return "movpi45\t%0, %1";
270 case 14:
271 return "movi55\t%0, %1";
272 case 15:
273 return "movi\t%0, %1";
274 case 16:
275 return "sethi\t%0, hi20(%1)";
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);
289 default:
290 gcc_unreachable ();
291 }
292 }
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")])
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.
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"))]
303 ""
304 "la\t%0, %1"
305 [(set_attr "type" "alu")
306 (set_attr "length" "8")])
307
308
309 (define_insn "sethi"
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
318 (define_insn "lo_sum"
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 ;; ----------------------------------------------------------------------------
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 })
426
427 ;; Arithmetic instructions.
428
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")))]
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 }
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")])
471
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")))]
476 ""
477 "@
478 sub45\t%0, %2
479 sub333\t%0, %1, %2
480 subri\t%0, %2, %1
481 sub\t%0, %1, %2"
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")))]
494 "TARGET_ISA_V3 && optimize_size
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 }
504 [(set_attr "type" "alu_shift")
505 (set_attr "combo" "2")
506 (set_attr "length" "4")])
507
508 (define_insn "*add_srli"
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"
514 "add_srli\t%0, %3, %1, %2"
515 [(set_attr "type" "alu_shift")
516 (set_attr "combo" "2")
517 (set_attr "length" "4")])
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"))))]
528 "TARGET_ISA_V3 && optimize_size
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 }
538 [(set_attr "type" "alu_shift")
539 (set_attr "combo" "2")
540 (set_attr "length" "4")])
541
542 (define_insn "*sub_srli"
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"
548 "sub_srli\t%0, %1, %2, %3"
549 [(set_attr "type" "alu_shift")
550 (set_attr "combo" "2")
551 (set_attr "length" "4")])
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 "@
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")])
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"
574 [(set_attr "type" "mul")
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"
583 [(set_attr "type" "mul")
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"
596 [(set_attr "type" "mac")
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"
606 [(set_attr "type" "mac")
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"
616 [(set_attr "type" "mac")
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"
630 [(set_attr "type" "div")
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"
641 [(set_attr "type" "div")
642 (set_attr "length" "4")])
643
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")])
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
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")))]
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:
730 return "bmski33\t%0, %B2";
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:
744 return "bclr\t%0, %1, %b2";
745
746 default:
747 gcc_unreachable ();
748 }
749 }
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")])
753
754 (define_insn "*and_slli"
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"
760 "and_slli\t%0, %3, %1, %2"
761 [(set_attr "type" "alu_shift")
762 (set_attr "length" "4")])
763
764 (define_insn "*and_srli"
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"
770 "and_srli\t%0, %3, %1, %2"
771 [(set_attr "type" "alu_shift")
772 (set_attr "length" "4")])
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.
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" "")))]
786 ""
787 {
788 if (!nds32_ior_operand (operands[2], SImode))
789 operands[2] = force_reg (SImode, operands[2]);
790 })
791
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")])
805
806 (define_insn "*or_slli"
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"
812 "or_slli\t%0, %3, %1, %2"
813 [(set_attr "type" "alu_shift")
814 (set_attr "length" "4")])
815
816 (define_insn "*or_srli"
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"
822 "or_srli\t%0, %3, %1, %2"
823 [(set_attr "type" "alu_shift")
824 (set_attr "length" "4")])
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.
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" "")))]
838 ""
839 {
840 if (!nds32_xor_operand (operands[2], SImode))
841 operands[2] = force_reg (SImode, operands[2]);
842 })
843
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")])
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")
861 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
862 (match_operand:SI 3 "register_operand" " r")))]
863 "TARGET_ISA_V3 && optimize_size"
864 "xor_slli\t%0, %3, %1, %2"
865 [(set_attr "type" "alu_shift")
866 (set_attr "length" "4")])
867
868 (define_insn "*xor_srli"
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"
874 "xor_srli\t%0, %3, %1, %2"
875 [(set_attr "type" "alu_shift")
876 (set_attr "length" "4")])
877
878 ;; Rotate Right Instructions.
879
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")))]
884 ""
885 "@
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")])
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"
902 [(set (match_operand:SI 0 "register_operand" "=l, r")
903 (neg:SI (match_operand:SI 1 "register_operand" " l, r")))]
904 ""
905 "@
906 neg33\t%0, %1
907 subri\t%0, %1, 0"
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 })
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"
1006 [(set_attr "type" "alu,alu")
1007 (set_attr "length" " 2, 4")
1008 (set_attr "feature" "v3m, v1")])
1009
1010
1011 ;; ----------------------------------------------------------------------------
1012
1013 ;; Shift instructions.
1014
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" "")))]
1019 ""
1020 {
1021 if (operands[2] == const0_rtx)
1022 {
1023 emit_move_insn (operands[0], operands[1]);
1024 DONE;
1025 }
1026 })
1027
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")))]
1032 ""
1033 "@
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")])
1040
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")))]
1045 ""
1046 "@
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")])
1066
1067
1068 ;; ----------------------------------------------------------------------------
1069
1070 ;; ----------------------------------------------------------------------------
1071 ;; Conditional Move patterns
1072 ;; ----------------------------------------------------------------------------
1073
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"
1080 {
1081 enum nds32_expand_result_type result = nds32_expand_movcc (operands);
1082 switch (result)
1083 {
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 ();
1094 }
1095 })
1096
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")
1100 (const_int 0))
1101 (match_operand:QIHISI 2 "register_operand" " r, 0")
1102 (match_operand:QIHISI 3 "register_operand" " 0, r")))]
1103 "TARGET_CMOV"
1104 "@
1105 cmovz\t%0, %2, %1
1106 cmovn\t%0, %3, %1"
1107 [(set_attr "type" "alu")
1108 (set_attr "length" "4")])
1109
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")
1113 (const_int 0))
1114 (match_operand:QIHISI 2 "register_operand" " r, 0")
1115 (match_operand:QIHISI 3 "register_operand" " 0, r")))]
1116 "TARGET_CMOV"
1117 "@
1118 cmovn\t%0, %2, %1
1119 cmovz\t%0, %3, %1"
1120 [(set_attr "type" "alu")
1121 (set_attr "length" "4")])
1122
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")])
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 {
1147 enum nds32_expand_result_type result = nds32_expand_cbranch (operands);
1148 switch (result)
1149 {
1150 case EXPAND_DONE:
1151 DONE;
1152 break;
1153 case EXPAND_FAIL:
1154 FAIL;
1155 break;
1156 case EXPAND_CREATE_TEMPLATE:
1157 break;
1158 default:
1159 gcc_unreachable ();
1160 }
1161 })
1162
1163
1164 (define_insn "cbranchsi4_equality_zero"
1165 [(set (pc)
1166 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1167 [(match_operand:SI 1 "register_operand" "t,l, r")
1168 (const_int 0)])
1169 (label_ref (match_operand 2 "" ""))
1170 (pc)))]
1171 ""
1172 {
1173 return nds32_output_cbranchsi4_equality_zero (insn, operands);
1174 }
1175 [(set_attr "type" "branch")
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 ])
1189 (set_attr_alternative "length"
1190 [
1191 ;; Alternative 0
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)")
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)
1224 (const_int 10))
1225 (const_int 10))
1226 ])])
1227
1228
1229 ;; This pattern is dedicated to V2 ISA,
1230 ;; because V2 DOES NOT HAVE beqc/bnec instruction.
1231 (define_insn "cbranchsi4_equality_reg"
1232 [(set (pc)
1233 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1234 [(match_operand:SI 1 "register_operand" "v, r")
1235 (match_operand:SI 2 "register_operand" "l, r")])
1236 (label_ref (match_operand 3 "" ""))
1237 (pc)))]
1238 "TARGET_ISA_V2"
1239 {
1240 return nds32_output_cbranchsi4_equality_reg (insn, operands);
1241 }
1242 [(set_attr "type" "branch")
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 ])])
1274
1275
1276 ;; This pattern is dedicated to V3/V3M,
1277 ;; because V3/V3M DO HAVE beqc/bnec instruction.
1278 (define_insn "cbranchsi4_equality_reg_or_const_int"
1279 [(set (pc)
1280 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1281 [(match_operand:SI 1 "register_operand" "v, r, r")
1282 (match_operand:SI 2 "nds32_rimm11s_operand" "l, r, Is11")])
1283 (label_ref (match_operand 3 "" ""))
1284 (pc)))]
1285 "TARGET_ISA_V3 || TARGET_ISA_V3M"
1286 {
1287 return nds32_output_cbranchsi4_equality_reg_or_const_int (insn, operands);
1288 }
1289 [(set_attr "type" "branch")
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 ])
1301 (set_attr_alternative "length"
1302 [
1303 ;; Alternative 0
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))
1315 ;; Alternative 1
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))
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 {
1341 return nds32_output_cbranchsi4_greater_less_zero (insn, operands);
1342 }
1343 [(set_attr "type" "branch")
1344 (set (attr "length")
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)))])
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 {
1360 enum nds32_expand_result_type result = nds32_expand_cstore (operands);
1361 switch (result)
1362 {
1363 case EXPAND_DONE:
1364 DONE;
1365 break;
1366 case EXPAND_FAIL:
1367 FAIL;
1368 break;
1369 case EXPAND_CREATE_TEMPLATE:
1370 break;
1371 default:
1372 gcc_unreachable ();
1373 }
1374 })
1375
1376
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")))]
1394 ""
1395 "@
1396 slts45\t%1, %2
1397 sltsi45\t%1, %2
1398 slts\t%0, %1, %2
1399 sltsi\t%0, %1, %2"
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")])
1413
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")))]
1431 ""
1432 "@
1433 slt45\t%1, %2
1434 slti45\t%1, %2
1435 slt\t%0, %1, %2
1436 slti\t%0, %1, %2"
1437 [(set_attr "type" "alu, alu, alu, alu")
1438 (set_attr "length" " 2, 2, 4, 4")])
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")
1471 (set_attr "enabled" "yes")
1472 (set (attr "length")
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))
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 "@
1486 jr5\t%0
1487 jr\t%0"
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 ""
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 }
1523 )
1524
1525 (define_insn "call_internal"
1526 [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, S"))
1527 (match_operand 1))
1528 (clobber (reg:SI LP_REGNUM))
1529 (clobber (reg:SI TA_REGNUM))])]
1530 ""
1531 {
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 }
1558 }
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 )
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 ""
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 }
1610 )
1611
1612 (define_insn "call_value_internal"
1613 [(parallel [(set (match_operand 0)
1614 (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, S"))
1615 (match_operand 2)))
1616 (clobber (reg:SI LP_REGNUM))
1617 (clobber (reg:SI TA_REGNUM))])]
1618 ""
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 )
1663
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 "" "")])]
1671 ""
1672 {
1673 int i;
1674
1675 emit_call_insn (gen_call (operands[0], const0_rtx));
1676
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 })
1690
1691 ;; ----------------------------------------------------------------------------
1692
1693 ;; The sibcall patterns.
1694
1695 ;; sibcall
1696 ;; sibcall_internal
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 ""
1704 {
1705 rtx sym = XEXP (operands[0], 0);
1706
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 })
1715
1716 (define_insn "sibcall_internal"
1717 [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, S"))
1718 (match_operand 1))
1719 (clobber (reg:SI TA_REGNUM))
1720 (return)])]
1721 ""
1722 {
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 }
1738 }
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 )
1755
1756 ;; sibcall_value
1757 ;; sibcall_value_internal
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 ""
1767 {
1768 rtx sym = XEXP (operands[1], 0);
1769
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"
1780 [(parallel [(set (match_operand 0)
1781 (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, S"))
1782 (match_operand 2)))
1783 (clobber (reg:SI TA_REGNUM))
1784 (return)])]
1785 ""
1786 {
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 }
1802 }
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 )
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.
1828 In addition, we need to check if v3push is indeed available. */
1829 if (NDS32_V3PUSH_AVAILABLE_P)
1830 nds32_expand_prologue_v3push ();
1831 else
1832 nds32_expand_prologue ();
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
1844 DONE;
1845 })
1846
1847 (define_expand "epilogue" [(const_int 0)]
1848 ""
1849 {
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
1860 /* Note that only under V3/V3M ISA, we could use v3pop epilogue.
1861 In addition, we need to check if v3push is indeed available. */
1862 if (NDS32_V3PUSH_AVAILABLE_P)
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. */
1875 nds32_expand_epilogue (true);
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")
1893 (set_attr "enabled" "yes")
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 }
1917 [(set_attr "type" "store_multiple")
1918 (set_attr "combo" "12")
1919 (set_attr "enabled" "yes")
1920 (set (attr "length")
1921 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
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 }
1938 [(set_attr "type" "load_multiple")
1939 (set_attr "combo" "12")
1940 (set_attr "enabled" "yes")
1941 (set (attr "length")
1942 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
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"
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"
1976 [(simple_return)]
1977 "!cfun->machine->fp_as_gp_p"
1978 ""
1979 )
1980
1981 (define_insn "*nds32_return"
1982 [(parallel [(return)
1983 (clobber (reg:SI FP_REGNUM))])]
1984 ""
1985 {
1986 return nds32_output_return ();
1987 }
1988 [(set_attr "type" "branch")
1989 (set_attr "enabled" "yes")
1990 (set_attr "length" "4")])
1991
1992 (define_insn "return_internal"
1993 [(simple_return)]
1994 ""
1995 {
1996 if (nds32_isr_function_critical_p (current_function_decl))
1997 return "iret";
1998
1999 if (TARGET_16_BIT)
2000 return "ret5";
2001 else
2002 return "ret";
2003 }
2004 [(set_attr "type" "branch")
2005 (set_attr "enabled" "yes")
2006 (set (attr "length")
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))))])
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;
2046 rtx tmp_reg;
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
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));
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 }
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)))])
2116
2117 ;; ----------------------------------------------------------------------------
2118
2119 ;; Performance Extension
2120
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
2135 (define_insn "clzsi2"
2136 [(set (match_operand:SI 0 "register_operand" "=r")
2137 (clz:SI (match_operand:SI 1 "register_operand" " r")))]
2138 "TARGET_EXT_PERF"
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")))]
2147 "TARGET_EXT_PERF"
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")))]
2156 "TARGET_EXT_PERF"
2157 "min\t%0, %1, %2"
2158 [(set_attr "type" "alu")
2159 (set_attr "length" "4")])
2160
2161 (define_insn "btst"
2162 [(set (match_operand:SI 0 "register_operand" "= r")
2163 (zero_extract:SI (match_operand:SI 1 "register_operand" " r")
2164 (const_int 1)
2165 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")))]
2166 "TARGET_EXT_PERF"
2167 "btst\t%0, %1, %2"
2168 [(set_attr "type" "alu")
2169 (set_attr "length" "4")])
2170
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
2186 ;; ----------------------------------------------------------------------------
2187
2188 ;; Pseudo NOPs
2189
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
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
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
2254 ;; ----------------------------------------------------------------------------
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 ;; ----------------------------------------------------------------------------