]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/nds32/nds32.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / nds32 / nds32.md
CommitLineData
9304f876 1;; Machine description of Andes NDS32 cpu for GNU compiler
8d9254fc 2;; Copyright (C) 2012-2020 Free Software Foundation, Inc.
9304f876
CJW
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
e2286268
MC
49;; Include floating-point patterns.
50(include "nds32-fpu.md")
51
9304f876
CJW
52;; Include peephole patterns.
53(include "nds32-peephole2.md")
54
55
b99353a2
KC
56;; ------------------------------------------------------------------------
57
58;; CPU pipeline model.
628332f8 59(define_attr "pipeline_model" "n7,n8,e8,n9,n10,graywolf,n13,simple"
b99353a2 60 (const
63ab910d
KC
61 (cond [(match_test "nds32_cpu_option == CPU_N7") (const_string "n7")
62 (match_test "nds32_cpu_option == CPU_E8") (const_string "e8")
7c1583bd 63 (match_test "nds32_cpu_option == CPU_N6 || nds32_cpu_option == CPU_N8") (const_string "n8")
8fd52141 64 (match_test "nds32_cpu_option == CPU_N9") (const_string "n9")
2f2ebf95 65 (match_test "nds32_cpu_option == CPU_N10") (const_string "n10")
628332f8 66 (match_test "nds32_cpu_option == CPU_GRAYWOLF") (const_string "graywolf")
96b07b10
KC
67 (match_test "nds32_cpu_option == CPU_N12") (const_string "n13")
68 (match_test "nds32_cpu_option == CPU_N13") (const_string "n13")
b99353a2
KC
69 (match_test "nds32_cpu_option == CPU_SIMPLE") (const_string "simple")]
70 (const_string "n9"))))
71
9304f876
CJW
72;; Insn type, it is used to default other attribute values.
73(define_attr "type"
2feae6cd 74 "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\
7c32ef41
MC
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"
9304f876
CJW
77 (const_string "unknown"))
78
0aa683b3
CJW
79;; Insn sub-type
80(define_attr "subtype"
7c32ef41 81 "simple,shift,saturation"
0aa683b3
CJW
82 (const_string "simple"))
83
9304f876
CJW
84;; Length, in bytes, default is 4-bytes.
85(define_attr "length" "" (const_int 4))
86
264159d2
KC
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"))
9304f876 91
9be6885b
KC
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"
e2286268 101 "v1,v2,v3m,v3,pe1,pe2,se,fpu"
9be6885b
KC
102 (const_string "v1"))
103
9304f876
CJW
104;; Enabled, which is used to enable/disable insn alternatives.
105;; Note that we use length and TARGET_16_BIT here as criteria.
9be6885b
KC
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.
30feb954 109(define_attr "enabled" "no,yes"
9be6885b
KC
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")
e2286268
MC
131 (const_string "yes")
132 (const_string "no"))
133 (eq_attr "feature" "fpu") (if_then_else (match_test "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE")
9be6885b
KC
134 (const_string "yes")
135 (const_string "no"))]
136 (const_string "yes"))))
9304f876
CJW
137
138
139;; ----------------------------------------------------------------------------
140
7c32ef41 141(include "nds32-dspext.md")
9304f876
CJW
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
76dc9cb5
CJW
148(define_expand "mov<mode>"
149 [(set (match_operand:QIHI 0 "general_operand" "")
150 (match_operand:QIHI 1 "general_operand" ""))]
9304f876
CJW
151 ""
152{
153 /* Need to force register if mem <- !reg. */
154 if (MEM_P (operands[0]) && !REG_P (operands[1]))
76dc9cb5 155 operands[1] = force_reg (<MODE>mode, operands[1]);
9304f876 156
76dc9cb5
CJW
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 }
9304f876
CJW
164})
165
2cf09a99
KC
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})
76dc9cb5 187
9304f876
CJW
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 }
85a98076
KLC
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 }
b26fa4f9
KLC
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 }
85a98076 238 }
9304f876
CJW
239})
240
241(define_insn "*mov<mode>"
e2286268
MC
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"))]
b4350271
KC
244 "register_operand(operands[0], <MODE>mode)
245 || register_operand(operands[1], <MODE>mode)"
9304f876
CJW
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:
9304f876 264 case 11:
8656bbcf 265 return nds32_output_16bit_load (operands, <byte>);
9304f876 266 case 12:
8656bbcf 267 return nds32_output_32bit_load (operands, <byte>);
9304f876 268 case 13:
8656bbcf 269 return "movpi45\t%0, %1";
9304f876 270 case 14:
8656bbcf 271 return "movi55\t%0, %1";
9304f876 272 case 15:
8656bbcf
SC
273 return "movi\t%0, %1";
274 case 16:
9304f876 275 return "sethi\t%0, hi20(%1)";
e2286268
MC
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);
9304f876
CJW
289 default:
290 gcc_unreachable ();
291 }
292}
e2286268
MC
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")])
9304f876
CJW
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.
c4d8d050 300(define_insn "move_addr"
b26fa4f9
KLC
301 [(set (match_operand:SI 0 "nds32_general_register_operand" "=l, r")
302 (match_operand:SI 1 "nds32_nonunspec_symbolic_operand" " i, i"))]
9304f876
CJW
303 ""
304 "la\t%0, %1"
5ba6d585 305 [(set_attr "type" "alu")
9304f876
CJW
306 (set_attr "length" "8")])
307
308
c4d8d050 309(define_insn "sethi"
9304f876
CJW
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
c4d8d050 318(define_insn "lo_sum"
9304f876
CJW
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;; ----------------------------------------------------------------------------
7c32ef41
MC
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})
9304f876
CJW
426
427;; Arithmetic instructions.
428
5c36be57
CJW
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")
7c32ef41 432 (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,IU06, Is15, r")))]
9304f876
CJW
433 ""
434{
435 switch (which_alternative)
436 {
437 case 0:
438 /* addi Rt4,Rt4,-x ==> subi45 Rt4,x
8a498f99 439 where 0 <= x <= 31 */
9304f876
CJW
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
8a498f99 444 where 0 <= x <= 7 */
9304f876
CJW
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}
9be6885b
KC
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")])
9304f876 471
5c36be57
CJW
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")))]
9304f876
CJW
476 ""
477 "@
9c1a4c0f
CJW
478 sub45\t%0, %2
479 sub333\t%0, %1, %2
480 subri\t%0, %2, %1
481 sub\t%0, %1, %2"
9304f876
CJW
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")
8a498f99 491 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
9304f876
CJW
492 (match_operand:SI 2 "immediate_operand" " i"))
493 (match_operand:SI 3 "register_operand" " r")))]
b9774a97 494 "TARGET_ISA_V3 && optimize_size
9304f876
CJW
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}
5ba6d585
KC
504 [(set_attr "type" "alu_shift")
505 (set_attr "combo" "2")
506 (set_attr "length" "4")])
9304f876
CJW
507
508(define_insn "*add_srli"
a3b13564
KC
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")))]
b9774a97 513 "TARGET_ISA_V3 && optimize_size"
9304f876 514 "add_srli\t%0, %3, %1, %2"
5ba6d585
KC
515 [(set_attr "type" "alu_shift")
516 (set_attr "combo" "2")
517 (set_attr "length" "4")])
9304f876
CJW
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"))))]
b9774a97 528 "TARGET_ISA_V3 && optimize_size
9304f876
CJW
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}
5ba6d585
KC
538 [(set_attr "type" "alu_shift")
539 (set_attr "combo" "2")
540 (set_attr "length" "4")])
9304f876
CJW
541
542(define_insn "*sub_srli"
77827557
CJW
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"))))]
b9774a97 547 "TARGET_ISA_V3 && optimize_size"
9304f876 548 "sub_srli\t%0, %1, %2, %3"
5ba6d585
KC
549 [(set_attr "type" "alu_shift")
550 (set_attr "combo" "2")
551 (set_attr "length" "4")])
9304f876
CJW
552
553
554;; Multiplication instructions.
555
556(define_insn "mulsi3"
73f793e3
RS
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")))]
9304f876
CJW
560 ""
561 "@
9c1a4c0f
CJW
562 mul33\t%0, %2
563 mul\t%0, %1, %2"
5ba6d585 564 [(set_attr "type" "mul,mul")
9be6885b
KC
565 (set_attr "length" " 2, 4")
566 (set_attr "feature" "v3m, v1")])
9304f876
CJW
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"
5ba6d585 574 [(set_attr "type" "mul")
9304f876
CJW
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"
5ba6d585 583 [(set_attr "type" "mul")
9304f876
CJW
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")
8a498f99
CJW
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"))))]
9304f876
CJW
594 ""
595 "maddr32\t%0, %1, %2"
5ba6d585 596 [(set_attr "type" "mac")
9304f876
CJW
597 (set_attr "length" "4")])
598
599(define_insn "*maddr32_1"
600 [(set (match_operand:SI 0 "register_operand" "=r")
8a498f99
CJW
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")))]
9304f876
CJW
604 ""
605 "maddr32\t%0, %1, %2"
5ba6d585 606 [(set_attr "type" "mac")
9304f876
CJW
607 (set_attr "length" "4")])
608
609(define_insn "*msubr32"
610 [(set (match_operand:SI 0 "register_operand" "=r")
8a498f99
CJW
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"))))]
9304f876
CJW
614 ""
615 "msubr32\t%0, %1, %2"
5ba6d585 616 [(set_attr "type" "mac")
9304f876
CJW
617 (set_attr "length" "4")])
618
619
620;; Div Instructions.
621
622(define_insn "divmodsi4"
623 [(set (match_operand:SI 0 "register_operand" "=r")
8a498f99
CJW
624 (div:SI (match_operand:SI 1 "register_operand" " r")
625 (match_operand:SI 2 "register_operand" " r")))
9304f876 626 (set (match_operand:SI 3 "register_operand" "=r")
8a498f99 627 (mod:SI (match_dup 1) (match_dup 2)))]
9304f876
CJW
628 ""
629 "divsr\t%0, %3, %1, %2"
5ba6d585 630 [(set_attr "type" "div")
9304f876
CJW
631 (set_attr "length" "4")])
632
633(define_insn "udivmodsi4"
634 [(set (match_operand:SI 0 "register_operand" "=r")
8a498f99
CJW
635 (udiv:SI (match_operand:SI 1 "register_operand" " r")
636 (match_operand:SI 2 "register_operand" " r")))
9304f876 637 (set (match_operand:SI 3 "register_operand" "=r")
8a498f99 638 (umod:SI (match_dup 1) (match_dup 2)))]
9304f876
CJW
639 ""
640 "divr\t%0, %3, %1, %2"
5ba6d585 641 [(set_attr "type" "div")
9304f876
CJW
642 (set_attr "length" "4")])
643
50ea1e4a
CJW
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")])
9304f876
CJW
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
a3b13564
KC
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")))]
9304f876
CJW
703 ""
704{
705 HOST_WIDE_INT mask = INTVAL (operands[2]);
9304f876
CJW
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:
a3b13564 730 return "bmski33\t%0, %B2";
9304f876
CJW
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:
a3b13564 744 return "bclr\t%0, %1, %b2";
9304f876
CJW
745
746 default:
747 gcc_unreachable ();
748 }
749}
9be6885b
KC
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")])
9304f876
CJW
753
754(define_insn "*and_slli"
77827557
CJW
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")))]
b9774a97 759 "TARGET_ISA_V3 && optimize_size"
9304f876 760 "and_slli\t%0, %3, %1, %2"
5ba6d585
KC
761 [(set_attr "type" "alu_shift")
762 (set_attr "length" "4")])
9304f876
CJW
763
764(define_insn "*and_srli"
77827557
CJW
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")))]
b9774a97 769 "TARGET_ISA_V3 && optimize_size"
9304f876 770 "and_srli\t%0, %3, %1, %2"
5ba6d585
KC
771 [(set_attr "type" "alu_shift")
772 (set_attr "length" "4")])
9304f876
CJW
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.
a3b13564
KC
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" "")))]
9304f876
CJW
786 ""
787{
a3b13564
KC
788 if (!nds32_ior_operand (operands[2], SImode))
789 operands[2] = force_reg (SImode, operands[2]);
790})
9304f876 791
a3b13564
KC
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")])
9304f876
CJW
805
806(define_insn "*or_slli"
a3b13564
KC
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")))]
b9774a97 811 "TARGET_ISA_V3 && optimize_size"
9304f876 812 "or_slli\t%0, %3, %1, %2"
5ba6d585
KC
813 [(set_attr "type" "alu_shift")
814 (set_attr "length" "4")])
9304f876
CJW
815
816(define_insn "*or_srli"
a3b13564
KC
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")))]
b9774a97 821 "TARGET_ISA_V3 && optimize_size"
9304f876 822 "or_srli\t%0, %3, %1, %2"
5ba6d585
KC
823 [(set_attr "type" "alu_shift")
824 (set_attr "length" "4")])
9304f876
CJW
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.
a3b13564
KC
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" "")))]
9304f876
CJW
838 ""
839{
a3b13564
KC
840 if (!nds32_xor_operand (operands[2], SImode))
841 operands[2] = force_reg (SImode, operands[2]);
842})
9304f876 843
a3b13564
KC
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"
9be6885b
KC
854 [(set_attr "type" "alu,alu,alu,alu")
855 (set_attr "length" " 2, 4, 4, 4")
856 (set_attr "feature" "v3m, v1, v1,pe1")])
9304f876
CJW
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")
a3b13564 861 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
9304f876 862 (match_operand:SI 3 "register_operand" " r")))]
b9774a97 863 "TARGET_ISA_V3 && optimize_size"
9304f876 864 "xor_slli\t%0, %3, %1, %2"
5ba6d585
KC
865 [(set_attr "type" "alu_shift")
866 (set_attr "length" "4")])
9304f876
CJW
867
868(define_insn "*xor_srli"
a3b13564
KC
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")))]
b9774a97 873 "TARGET_ISA_V3 && optimize_size"
9304f876 874 "xor_srli\t%0, %3, %1, %2"
5ba6d585
KC
875 [(set_attr "type" "alu_shift")
876 (set_attr "length" "4")])
9304f876
CJW
877
878;; Rotate Right Instructions.
879
a3b13564
KC
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")))]
9304f876
CJW
884 ""
885 "@
9c1a4c0f
CJW
886 rotri\t%0, %1, %2
887 rotr\t%0, %1, %2"
5ba6d585 888 [(set_attr "type" " alu, alu")
0aa683b3 889 (set_attr "subtype" "shift,shift")
5ba6d585 890 (set_attr "length" " 4, 4")])
9304f876
CJW
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"
3fbbd9e5
CJW
902 [(set (match_operand:SI 0 "register_operand" "=l, r")
903 (neg:SI (match_operand:SI 1 "register_operand" " l, r")))]
9304f876
CJW
904 ""
905 "@
906 neg33\t%0, %1
907 subri\t%0, %1, 0"
3fbbd9e5
CJW
908 [(set_attr "type" "alu,alu")
909 (set_attr "length" " 2, 4")
910 (set_attr "feature" "v3m, v1")])
9304f876 911
e2286268
MC
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
9304f876
CJW
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"
9be6885b
KC
1006 [(set_attr "type" "alu,alu")
1007 (set_attr "length" " 2, 4")
1008 (set_attr "feature" "v3m, v1")])
9304f876
CJW
1009
1010
1011;; ----------------------------------------------------------------------------
1012
1013;; Shift instructions.
1014
a3b13564
KC
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")))]
9304f876
CJW
1032 ""
1033 "@
9c1a4c0f
CJW
1034 slli333\t%0, %1, %2
1035 slli\t%0, %1, %2
1036 sll\t%0, %1, %2"
0aa683b3
CJW
1037 [(set_attr "type" " alu, alu, alu")
1038 (set_attr "subtype" "shift,shift,shift")
1039 (set_attr "length" " 2, 4, 4")])
a3b13564
KC
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")))]
9304f876
CJW
1045 ""
1046 "@
9c1a4c0f
CJW
1047 srai45\t%0, %2
1048 srai\t%0, %1, %2
1049 sra\t%0, %1, %2"
0aa683b3
CJW
1050 [(set_attr "type" " alu, alu, alu")
1051 (set_attr "subtype" "shift,shift,shift")
1052 (set_attr "length" " 2, 4, 4")])
9304f876 1053
a3b13564
KC
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")))]
9304f876
CJW
1058 ""
1059 "@
9c1a4c0f
CJW
1060 srli45\t%0, %2
1061 srli\t%0, %1, %2
1062 srl\t%0, %1, %2"
0aa683b3
CJW
1063 [(set_attr "type" " alu, alu, alu")
1064 (set_attr "subtype" "shift,shift,shift")
1065 (set_attr "length" " 2, 4, 4")])
9304f876
CJW
1066
1067
1068;; ----------------------------------------------------------------------------
1069
1070;; ----------------------------------------------------------------------------
1071;; Conditional Move patterns
1072;; ----------------------------------------------------------------------------
1073
6e9ca932
CJW
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"
9304f876 1080{
6e9ca932
CJW
1081 enum nds32_expand_result_type result = nds32_expand_movcc (operands);
1082 switch (result)
9304f876 1083 {
6e9ca932
CJW
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 ();
9304f876 1094 }
9304f876
CJW
1095})
1096
6e9ca932
CJW
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")
9304f876 1100 (const_int 0))
6e9ca932
CJW
1101 (match_operand:QIHISI 2 "register_operand" " r, 0")
1102 (match_operand:QIHISI 3 "register_operand" " 0, r")))]
9304f876
CJW
1103 "TARGET_CMOV"
1104 "@
1105 cmovz\t%0, %2, %1
1106 cmovn\t%0, %3, %1"
5ba6d585 1107 [(set_attr "type" "alu")
9304f876
CJW
1108 (set_attr "length" "4")])
1109
6e9ca932
CJW
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")
9304f876 1113 (const_int 0))
6e9ca932
CJW
1114 (match_operand:QIHISI 2 "register_operand" " r, 0")
1115 (match_operand:QIHISI 3 "register_operand" " 0, r")))]
9304f876
CJW
1116 "TARGET_CMOV"
1117 "@
1118 cmovn\t%0, %2, %1
1119 cmovz\t%0, %3, %1"
5ba6d585 1120 [(set_attr "type" "alu")
9304f876
CJW
1121 (set_attr "length" "4")])
1122
6e9ca932
CJW
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")])
9304f876
CJW
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{
6e9ca932
CJW
1147 enum nds32_expand_result_type result = nds32_expand_cbranch (operands);
1148 switch (result)
9304f876 1149 {
6e9ca932 1150 case EXPAND_DONE:
9304f876 1151 DONE;
6e9ca932
CJW
1152 break;
1153 case EXPAND_FAIL:
9304f876 1154 FAIL;
6e9ca932
CJW
1155 break;
1156 case EXPAND_CREATE_TEMPLATE:
1157 break;
1158 default:
1159 gcc_unreachable ();
9304f876 1160 }
9304f876
CJW
1161})
1162
1163
6e9ca932 1164(define_insn "cbranchsi4_equality_zero"
9304f876
CJW
1165 [(set (pc)
1166 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
6e9ca932 1167 [(match_operand:SI 1 "register_operand" "t,l, r")
9304f876
CJW
1168 (const_int 0)])
1169 (label_ref (match_operand 2 "" ""))
1170 (pc)))]
1171 ""
1172{
6e9ca932 1173 return nds32_output_cbranchsi4_equality_zero (insn, operands);
9304f876
CJW
1174}
1175 [(set_attr "type" "branch")
6e9ca932
CJW
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 ])
9304f876
CJW
1189 (set_attr_alternative "length"
1190 [
1191 ;; Alternative 0
6e9ca932
CJW
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)))
9304f876 1195 (if_then_else (match_test "TARGET_16_BIT")
6e9ca932
CJW
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))
9304f876 1205 ;; Alternative 1
6e9ca932
CJW
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)")
9304f876
CJW
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)
6e9ca932
CJW
1224 (const_int 10))
1225 (const_int 10))
9304f876
CJW
1226 ])])
1227
1228
1229;; This pattern is dedicated to V2 ISA,
1230;; because V2 DOES NOT HAVE beqc/bnec instruction.
6e9ca932 1231(define_insn "cbranchsi4_equality_reg"
9304f876
CJW
1232 [(set (pc)
1233 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
6e9ca932
CJW
1234 [(match_operand:SI 1 "register_operand" "v, r")
1235 (match_operand:SI 2 "register_operand" "l, r")])
9304f876
CJW
1236 (label_ref (match_operand 3 "" ""))
1237 (pc)))]
1238 "TARGET_ISA_V2"
1239{
6e9ca932 1240 return nds32_output_cbranchsi4_equality_reg (insn, operands);
9304f876
CJW
1241}
1242 [(set_attr "type" "branch")
6e9ca932
CJW
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 ])])
9304f876
CJW
1274
1275
1276;; This pattern is dedicated to V3/V3M,
1277;; because V3/V3M DO HAVE beqc/bnec instruction.
6e9ca932 1278(define_insn "cbranchsi4_equality_reg_or_const_int"
9304f876
CJW
1279 [(set (pc)
1280 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
6e9ca932
CJW
1281 [(match_operand:SI 1 "register_operand" "v, r, r")
1282 (match_operand:SI 2 "nds32_rimm11s_operand" "l, r, Is11")])
9304f876
CJW
1283 (label_ref (match_operand 3 "" ""))
1284 (pc)))]
1285 "TARGET_ISA_V3 || TARGET_ISA_V3M"
1286{
6e9ca932 1287 return nds32_output_cbranchsi4_equality_reg_or_const_int (insn, operands);
9304f876
CJW
1288}
1289 [(set_attr "type" "branch")
6e9ca932
CJW
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 ])
9304f876
CJW
1301 (set_attr_alternative "length"
1302 [
1303 ;; Alternative 0
6e9ca932
CJW
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))
9304f876 1315 ;; Alternative 1
6e9ca932
CJW
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))
9304f876
CJW
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{
6e9ca932 1341 return nds32_output_cbranchsi4_greater_less_zero (insn, operands);
9304f876
CJW
1342}
1343 [(set_attr "type" "branch")
1344 (set (attr "length")
6e9ca932
CJW
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)))])
9304f876
CJW
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{
6e9ca932
CJW
1360 enum nds32_expand_result_type result = nds32_expand_cstore (operands);
1361 switch (result)
9304f876 1362 {
6e9ca932 1363 case EXPAND_DONE:
9304f876 1364 DONE;
6e9ca932
CJW
1365 break;
1366 case EXPAND_FAIL:
1367 FAIL;
1368 break;
1369 case EXPAND_CREATE_TEMPLATE:
1370 break;
9304f876
CJW
1371 default:
1372 gcc_unreachable ();
1373 }
1374})
1375
1376
6e9ca932
CJW
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")))]
9304f876
CJW
1394 ""
1395 "@
1396 slts45\t%1, %2
1397 sltsi45\t%1, %2
1398 slts\t%0, %1, %2
1399 sltsi\t%0, %1, %2"
6e9ca932
CJW
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})
9304f876 1426
6e9ca932
CJW
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")))]
9304f876
CJW
1431 ""
1432 "@
1433 slt45\t%1, %2
1434 slti45\t%1, %2
1435 slt\t%0, %1, %2
1436 slti\t%0, %1, %2"
5ba6d585
KC
1437 [(set_attr "type" "alu, alu, alu, alu")
1438 (set_attr "length" " 2, 2, 4, 4")])
9304f876
CJW
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")
30feb954 1471 (set_attr "enabled" "yes")
9304f876 1472 (set (attr "length")
6e9ca932
CJW
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))
9304f876
CJW
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 "@
9c1a4c0f
CJW
1486 jr5\t%0
1487 jr\t%0"
9304f876
CJW
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
026c3cfd 1493;; the address of the function.
9304f876
CJW
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))
1f7b8028
CJW
1500 (clobber (reg:SI LP_REGNUM))
1501 (clobber (reg:SI TA_REGNUM))])]
9304f876 1502 ""
85a98076
KLC
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 }
9304f876
CJW
1523)
1524
f4670673 1525(define_insn "call_internal"
d29cce74 1526 [(parallel [(call (mem:SI (match_operand:SI 0 "nds32_call_address_operand" "r, S"))
9304f876 1527 (match_operand 1))
1f7b8028
CJW
1528 (clobber (reg:SI LP_REGNUM))
1529 (clobber (reg:SI TA_REGNUM))])]
9304f876 1530 ""
1f7b8028 1531{
43fa41c1
CJW
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 ();
f4670673
CJW
1535 switch (which_alternative)
1536 {
1537 case 0:
1538 if (TARGET_16_BIT)
43fa41c1
CJW
1539 {
1540 if (align_p)
1541 return "jral5\t%0\;.align 2";
1542 else
1543 return "jral5\t%0";
1544 }
f4670673 1545 else
43fa41c1
CJW
1546 {
1547 if (align_p)
1548 return "jral\t%0\;.align 2";
1549 else
1550 return "jral\t%0";
1551 }
f4670673
CJW
1552 case 1:
1553 return nds32_output_call (insn, operands, operands[0],
43fa41c1 1554 "bal\t%0", "jal\t%0", align_p);
f4670673
CJW
1555 default:
1556 gcc_unreachable ();
1557 }
1f7b8028 1558}
f4670673
CJW
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
b26fa4f9
KLC
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)))
f4670673
CJW
1573 ])]
1574)
9304f876
CJW
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)))
1f7b8028
CJW
1586 (clobber (reg:SI LP_REGNUM))
1587 (clobber (reg:SI TA_REGNUM))])]
85a98076
KLC
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)
9304f876 1611
f4670673 1612(define_insn "call_value_internal"
9304f876 1613 [(parallel [(set (match_operand 0)
d29cce74 1614 (call (mem:SI (match_operand:SI 1 "nds32_call_address_operand" "r, S"))
9304f876 1615 (match_operand 2)))
1f7b8028
CJW
1616 (clobber (reg:SI LP_REGNUM))
1617 (clobber (reg:SI TA_REGNUM))])]
9304f876 1618 ""
f4670673 1619{
43fa41c1
CJW
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 ();
f4670673
CJW
1623 switch (which_alternative)
1624 {
1625 case 0:
1626 if (TARGET_16_BIT)
43fa41c1
CJW
1627 {
1628 if (align_p)
1629 return "jral5\t%1\;.align 2";
1630 else
1631 return "jral5\t%1";
1632 }
f4670673 1633 else
43fa41c1
CJW
1634 {
1635 if (align_p)
1636 return "jral\t%1\;.align 2";
1637 else
1638 return "jral\t%1";
1639 }
f4670673
CJW
1640 case 1:
1641 return nds32_output_call (insn, operands, operands[1],
43fa41c1 1642 "bal\t%1", "jal\t%1", align_p);
f4670673
CJW
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
b26fa4f9
KLC
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)))
f4670673
CJW
1661 ])]
1662)
9304f876 1663
f4670673
CJW
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 "" "")])]
9304f876 1671 ""
1f7b8028 1672{
f4670673 1673 int i;
9304f876 1674
f4670673
CJW
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})
9304f876 1690
d6529176
CJW
1691;; ----------------------------------------------------------------------------
1692
1693;; The sibcall patterns.
1694
1695;; sibcall
cc48a87f 1696;; sibcall_internal
d6529176
CJW
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)])]
85a98076
KLC
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})
d6529176 1715
cc48a87f 1716(define_insn "sibcall_internal"
d29cce74 1717 [(parallel [(call (mem:SI (match_operand:SI 0 "nds32_call_address_operand" "r, S"))
d6529176
CJW
1718 (match_operand 1))
1719 (clobber (reg:SI TA_REGNUM))
1720 (return)])]
1721 ""
1722{
cc48a87f
CJW
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 }
d6529176 1738}
30feb954 1739 [(set_attr "enabled" "yes")
cc48a87f
CJW
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
b26fa4f9
KLC
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)))
cc48a87f
CJW
1753 ])]
1754)
d6529176
CJW
1755
1756;; sibcall_value
cc48a87f 1757;; sibcall_value_internal
d6529176
CJW
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)])]
85a98076
KLC
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})
d6529176 1778
cc48a87f 1779(define_insn "sibcall_value_internal"
d6529176 1780 [(parallel [(set (match_operand 0)
d29cce74 1781 (call (mem:SI (match_operand:SI 1 "nds32_call_address_operand" "r, S"))
d6529176
CJW
1782 (match_operand 2)))
1783 (clobber (reg:SI TA_REGNUM))
1784 (return)])]
1785 ""
1786{
cc48a87f
CJW
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 }
d6529176 1802}
30feb954 1803 [(set_attr "enabled" "yes")
cc48a87f
CJW
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
b26fa4f9
KLC
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)))
cc48a87f
CJW
1817 ])]
1818)
d6529176
CJW
1819
1820;; ----------------------------------------------------------------------------
1821
9304f876
CJW
1822;; prologue and epilogue.
1823
1824(define_expand "prologue" [(const_int 0)]
1825 ""
1826{
2da1e7c0 1827 /* Note that only under V3/V3M ISA, we could use v3push prologue.
a6c7e777
MC
1828 In addition, we need to check if v3push is indeed available. */
1829 if (NDS32_V3PUSH_AVAILABLE_P)
9304f876
CJW
1830 nds32_expand_prologue_v3push ();
1831 else
1832 nds32_expand_prologue ();
2140297c
CJW
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
9304f876
CJW
1844 DONE;
1845})
1846
1847(define_expand "epilogue" [(const_int 0)]
1848 ""
1849{
2140297c
CJW
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
2da1e7c0 1860 /* Note that only under V3/V3M ISA, we could use v3pop epilogue.
a6c7e777
MC
1861 In addition, we need to check if v3push is indeed available. */
1862 if (NDS32_V3PUSH_AVAILABLE_P)
d6529176
CJW
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. */
a6c7e777 1875 nds32_expand_epilogue (true);
d6529176 1876
9304f876
CJW
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")
30feb954 1893 (set_attr "enabled" "yes")
9304f876
CJW
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{
6f3d3f9c 1915 return nds32_output_stack_push (operands[0]);
9304f876 1916}
264159d2
KC
1917 [(set_attr "type" "store_multiple")
1918 (set_attr "combo" "12")
30feb954 1919 (set_attr "enabled" "yes")
9304f876 1920 (set (attr "length")
9865d240 1921 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
9304f876
CJW
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{
6f3d3f9c 1936 return nds32_output_stack_pop (operands[0]);
9304f876 1937}
264159d2
KC
1938 [(set_attr "type" "load_multiple")
1939 (set_attr "combo" "12")
30feb954 1940 (set_attr "enabled" "yes")
9304f876 1941 (set (attr "length")
9865d240 1942 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
9304f876
CJW
1943 (const_int 2)
1944 (const_int 4)))])
1945
1946
1947;; ----------------------------------------------------------------------------
03390cda 1948;; Return operation patterns
9304f876
CJW
1949;; ----------------------------------------------------------------------------
1950
03390cda
CJW
1951;; Use this pattern to expand a return instruction
1952;; with simple_return rtx if no epilogue is required.
1953(define_expand "return"
f4670673
CJW
1954 [(parallel [(return)
1955 (clobber (reg:SI FP_REGNUM))])]
03390cda 1956 "nds32_can_use_return_insn ()"
f4670673
CJW
1957{
1958 /* Emit as the simple return. */
2140297c
CJW
1959 if (!cfun->machine->fp_as_gp_p
1960 && cfun->machine->naked_p
f4670673
CJW
1961 && (cfun->machine->va_args_size == 0))
1962 {
1963 emit_jump_insn (gen_return_internal ());
1964 DONE;
1965 }
1966})
9304f876 1967
03390cda
CJW
1968;; This pattern is expanded only by the shrink-wrapping optimization
1969;; on paths where the function prologue has not been executed.
2140297c
CJW
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.
03390cda
CJW
1975(define_expand "simple_return"
1976 [(simple_return)]
2140297c 1977 "!cfun->machine->fp_as_gp_p"
03390cda
CJW
1978 ""
1979)
1980
f4670673
CJW
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
03390cda
CJW
1992(define_insn "return_internal"
1993 [(simple_return)]
9304f876
CJW
1994 ""
1995{
a4931745
CJW
1996 if (nds32_isr_function_critical_p (current_function_decl))
1997 return "iret";
1998
9304f876
CJW
1999 if (TARGET_16_BIT)
2000 return "ret5";
2001 else
2002 return "ret";
2003}
03390cda 2004 [(set_attr "type" "branch")
30feb954 2005 (set_attr "enabled" "yes")
9304f876 2006 (set (attr "length")
a4931745
CJW
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))))])
9304f876
CJW
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;
b26fa4f9 2046 rtx tmp_reg;
9304f876
CJW
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,
8a498f99
CJW
2055 we need to force register first because our addsi3 pattern
2056 only accept nds32_rimm15s_operand predicate. */
9304f876
CJW
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
b26fa4f9
KLC
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));
9304f876
CJW
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)))
24f036fb 2102 (clobber (match_operand:SI 2 "register_operand" "=r"))
9304f876
CJW
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}
b26fa4f9
KLC
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)))])
9304f876
CJW
2116
2117;; ----------------------------------------------------------------------------
2118
2119;; Performance Extension
2120
8c9babb8
CJW
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
9304f876
CJW
2135(define_insn "clzsi2"
2136 [(set (match_operand:SI 0 "register_operand" "=r")
2137 (clz:SI (match_operand:SI 1 "register_operand" " r")))]
aa4b851c 2138 "TARGET_EXT_PERF"
9304f876
CJW
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")))]
aa4b851c 2147 "TARGET_EXT_PERF"
9304f876
CJW
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")))]
aa4b851c 2156 "TARGET_EXT_PERF"
9304f876
CJW
2157 "min\t%0, %1, %2"
2158 [(set_attr "type" "alu")
2159 (set_attr "length" "4")])
2160
2feae6cd
MC
2161(define_insn "btst"
2162 [(set (match_operand:SI 0 "register_operand" "= r")
2163 (zero_extract:SI (match_operand:SI 1 "register_operand" " r")
9304f876 2164 (const_int 1)
2feae6cd 2165 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")))]
aa4b851c 2166 "TARGET_EXT_PERF"
9304f876
CJW
2167 "btst\t%0, %1, %2"
2168 [(set_attr "type" "alu")
2169 (set_attr "length" "4")])
2170
2feae6cd
MC
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
9304f876 2186;; ----------------------------------------------------------------------------
aa2642ef
CJW
2187
2188;; Pseudo NOPs
2189
c4d8d050
CJW
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
2140297c
CJW
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
aa2642ef
CJW
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
b26fa4f9
KLC
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)))]
cf3cd43d 2229 "TARGET_LINUX_ABI || flag_pic"
b26fa4f9
KLC
2230 "add5.pc\t%0"
2231 [(set_attr "type" "alu")
2232 (set_attr "length" "4")]
2233)
0be3bad7
CJW
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
aa2642ef 2254;; ----------------------------------------------------------------------------
ca3a4a55
CJW
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;; ----------------------------------------------------------------------------
b26fa4f9 2318
c5ca5ad0
MC
2319;; Patterns for __builtin_trap.
2320(define_insn "trap"
2321 [(trap_if (const_int 1) (const_int 0))]
2322 ""
2323 "trap\t0")
2324
2325;; ----------------------------------------------------------------------------
2326
b26fa4f9
KLC
2327;; Patterns for TLS.
2328;; The following two tls patterns don't be expanded directly because the
2329;; intermediate value may be spilled into the stack. As a result, it is
2330;; hard to analyze the define-use chain in the relax_opt pass.
2331
2332
2333;; There is a unspec operand to record RELAX_GROUP number because each
2334;; emitted instruction need a relax_hint above it.
2335(define_insn "tls_desc"
2336 [(set (reg:SI 0)
2337 (call (unspec_volatile:SI [(match_operand:SI 0 "nds32_symbolic_operand" "i")] UNSPEC_TLS_DESC)
2338 (const_int 1)))
2339 (use (unspec [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))
2340 (use (reg:SI GP_REGNUM))
2341 (clobber (reg:SI LP_REGNUM))
2342 (clobber (reg:SI TA_REGNUM))]
2343 ""
2344 {
2345 return nds32_output_tls_desc (operands);
2346 }
2347 [(set_attr "length" "20")
2348 (set_attr "type" "branch")]
2349)
2350
2351;; There is a unspec operand to record RELAX_GROUP number because each
2352;; emitted instruction need a relax_hint above it.
2353(define_insn "tls_ie"
2354 [(set (match_operand:SI 0 "register_operand" "=r")
2355 (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE))
2356 (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))
2357 (use (reg:SI GP_REGNUM))]
2358 ""
2359 {
2360 return nds32_output_tls_ie (operands);
2361 }
2362 [(set (attr "length") (if_then_else (match_test "flag_pic")
2363 (const_int 12)
2364 (const_int 8)))
2365 (set_attr "type" "misc")]
2366)
2367
0398ae78
MC
2368;; There is a unspec operand to record RELAX_GROUP number because each
2369;; emitted instruction need a relax_hint above it.
2370(define_insn "tls_le"
2371 [(set (match_operand:SI 0 "register_operand" "=r")
2372 (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE))
2373 (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))]
2374 ""
2375 {
2376 return nds32_output_symrel (operands);
2377 }
2378 [(set_attr "length" "8")
2379 (set_attr "type" "misc")]
2380)
2381
b26fa4f9
KLC
2382;; The pattern is for some relaxation groups that have to keep addsi3 in 32-bit mode.
2383(define_insn "addsi3_32bit"
2384 [(set (match_operand:SI 0 "register_operand" "=r")
2385 (unspec:SI [(match_operand:SI 1 "register_operand" "%r")
2386 (match_operand:SI 2 "register_operand" " r")] UNSPEC_ADD32))]
2387 ""
2388 "add\t%0, %1, %2";
2389 [(set_attr "type" "alu")
2390 (set_attr "length" "4")
2391 (set_attr "feature" "v1")])
2392
0398ae78
MC
2393;; Patterns for PIC.
2394(define_insn "sym_got"
2395 [(set (match_operand:SI 0 "register_operand" "=r")
2396 (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_GOT))
2397 (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))]
2398 ""
2399 {
2400 return nds32_output_symrel (operands);
2401 }
2402 [(set_attr "length" "8")
2403 (set_attr "type" "misc")]
2404)
2405
b26fa4f9 2406;; ----------------------------------------------------------------------------