Fix build on sparc64-linux-gnu.
[official-gcc.git] / gcc / config / nds32 / nds32-doubleword.md
blob7ee6489d0341686c9c8f7cd398a9d082b0bc8221
1 ;; DImode/DFmode patterns description of Andes NDS32 cpu for GNU compiler
2 ;; Copyright (C) 2012-2018 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.
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.
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/>.
22 ;; -------------------------------------------------------------
23 ;; Move DImode/DFmode instructions.
24 ;; -------------------------------------------------------------
27 (define_expand "movdi"
28   [(set (match_operand:DI 0 "general_operand" "")
29         (match_operand:DI 1 "general_operand" ""))]
30   ""
32   /* Need to force register if mem <- !reg.  */
33   if (MEM_P (operands[0]) && !REG_P (operands[1]))
34     operands[1] = force_reg (DImode, operands[1]);
37 (define_expand "movdf"
38   [(set (match_operand:DF 0 "general_operand" "")
39         (match_operand:DF 1 "general_operand" ""))]
40   ""
42   /* Need to force register if mem <- !reg.  */
43   if (MEM_P (operands[0]) && !REG_P (operands[1]))
44     operands[1] = force_reg (DFmode, operands[1]);
48 (define_insn "move_<mode>"
49   [(set (match_operand:DIDF 0 "nonimmediate_operand" "=r, r,  r, r, Da, m, f, Q, f, *r, *f")
50         (match_operand:DIDF 1 "general_operand"      " r, i, Da, m,  r, r, Q, f, f, *f, *r"))]
51   "register_operand(operands[0], <MODE>mode)
52    || register_operand(operands[1], <MODE>mode)"
54   switch (which_alternative)
55     {
56     case 0:
57       return "movd44\t%0, %1";
58     case 1:
59       /* reg <- const_int, we ask gcc to split instruction.  */
60       return "#";
61     case 2:
62       /* The memory format is (mem (reg)),
63          we can generate 'lmw.bi' instruction.  */
64       return nds32_output_double (operands, true);
65     case 3:
66       /* We haven't 64-bit load instruction,
67          we split this pattern to two SImode pattern.  */
68       return "#";
69     case 4:
70       /* The memory format is (mem (reg)),
71          we can generate 'smw.bi' instruction.  */
72       return nds32_output_double (operands, false);
73     case 5:
74       /* We haven't 64-bit store instruction,
75          we split this pattern to two SImode pattern.  */
76       return "#";
77     case 6:
78       return nds32_output_float_load (operands);
79     case 7:
80       return nds32_output_float_store (operands);
81     case 8:
82       return "fcpysd\t%0, %1, %1";
83     case 9:
84       return "fmfdr\t%0, %1";
85     case 10:
86       return "fmtdr\t%1, %0";
87     default:
88       gcc_unreachable ();
89     }
91   [(set_attr "type"    "alu,alu,load,load,store,store,fload,fstore,fcpy,fmfdr,fmtdr")
92    (set_attr_alternative "length"
93      [
94        ;; Alternative 0
95        (if_then_else (match_test "!TARGET_16_BIT")
96                      (const_int 4)
97                      (const_int 2))
98        ;; Alternative 1
99        (const_int 16)
100        ;; Alternative 2
101        (const_int 4)
102        ;; Alternative 3
103        (const_int 8)
104        ;; Alternative 4
105        (const_int 4)
106        ;; Alternative 5
107        (const_int 8)
108        ;; Alternative 6
109        (const_int 4)
110        ;; Alternative 7
111        (const_int 4)
112        ;; Alternative 8
113        (const_int 4)
114        ;; Alternative 9
115        (const_int 4)
116        ;; Alternative 10
117        (const_int 4)
118      ])
119    (set_attr "feature" " v1, v1,  v1,  v1,   v1,   v1,    fpu,    fpu,    fpu,    fpu,    fpu")])
121 ;; Split move_di pattern when the hard register is odd.
122 (define_split
123   [(set (match_operand:DIDF 0 "register_operand" "")
124         (match_operand:DIDF 1 "register_operand" ""))]
125   "(NDS32_IS_GPR_REGNUM (REGNO (operands[0]))
126     && ((REGNO (operands[0]) & 0x1) == 1))
127    || (NDS32_IS_GPR_REGNUM (REGNO (operands[1]))
128        && ((REGNO (operands[1]) & 0x1) == 1))"
129   [(set (match_dup 2) (match_dup 3))
130    (set (match_dup 4) (match_dup 5))]
131   {
132      operands[2] = gen_lowpart (SImode, operands[0]);
133      operands[4] = gen_highpart (SImode, operands[0]);
134      operands[3] = gen_lowpart (SImode, operands[1]);
135      operands[5] = gen_highpart (SImode, operands[1]);
136   }
139 (define_split
140   [(set (match_operand:DIDF 0 "register_operand"     "")
141         (match_operand:DIDF 1 "const_double_operand" ""))]
142   "flag_pic || reload_completed"
143   [(set (match_dup 2) (match_dup 3))
144    (set (match_dup 4) (match_dup 5))]
146   /* Construct lowpart rtx.  */
147   operands[2] = gen_lowpart (SImode, operands[0]);
148   operands[3] = gen_lowpart (SImode, operands[1]);
150   /* Construct highpart rtx.  */
151   /* Note that operands[1] can be VOIDmode constant,
152      so we need to use gen_highpart_mode().
153      Refer to gcc/emit-rtl.c for more information.  */
154   operands[4] = gen_highpart (SImode, operands[0]);
155   operands[5] = gen_highpart_mode (SImode,
156                                    GET_MODE (operands[0]), operands[1]);
158   /* Actually we would like to create move behavior by ourself.
159      So that movsi expander could have chance to split large constant.  */
160   emit_move_insn (operands[2], operands[3]);
162   unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
163   if ((UINTVAL (operands[3]) & mask) == (UINTVAL (operands[5]) & mask))
164     emit_move_insn (operands[4], operands[2]);
165   else
166     emit_move_insn (operands[4], operands[5]);
167   DONE;
170 ;; There is 'movd44' instruction for DImode/DFmode movement under V3/V3M ISA.
171 ;; We only need to split it under V2 ISA or none-16-bit code generation.
172 (define_split
173   [(set (match_operand:DIDF 0 "register_operand" "")
174         (match_operand:DIDF 1 "register_operand" ""))]
175   "reload_completed
176    && (TARGET_ISA_V2 || !TARGET_16_BIT)
177    && NDS32_IS_GPR_REGNUM (REGNO (operands[0]))
178    && NDS32_IS_GPR_REGNUM (REGNO (operands[1]))"
179   [(set (match_dup 0) (match_dup 1))
180    (set (match_dup 2) (match_dup 3))]
182   operands[2] = gen_highpart (SImode, operands[0]);
183   operands[3] = gen_highpart (SImode, operands[1]);
184   operands[0] = gen_lowpart (SImode, operands[0]);
185   operands[1] = gen_lowpart (SImode, operands[1]);
187   /* Handle a partial overlap.  */
188   if (rtx_equal_p (operands[0], operands[3]))
189     {
190       rtx tmp0 = operands[0];
191       rtx tmp1 = operands[1];
193       operands[0] = operands[2];
194       operands[1] = operands[3];
195       operands[2] = tmp0;
196       operands[3] = tmp1;
197     }
200 (define_split
201   [(set (match_operand:DIDF 0 "nds32_general_register_operand" "")
202         (match_operand:DIDF 1 "memory_operand" ""))]
203   "reload_completed
204    && nds32_split_double_word_load_store_p (operands, true)"
205   [(set (match_dup 2) (match_dup 3))
206    (set (match_dup 4) (match_dup 5))]
208   nds32_spilt_doubleword (operands, true);
211 (define_split
212   [(set (match_operand:DIDF 0  "memory_operand" "")
213         (match_operand:DIDF 1  "nds32_general_register_operand" ""))]
214   "reload_completed
215    && nds32_split_double_word_load_store_p (operands, false)"
216   [(set (match_dup 2) (match_dup 3))
217    (set (match_dup 4) (match_dup 5))]
219   nds32_spilt_doubleword (operands, false);
222 ;; -------------------------------------------------------------
223 ;; Boolean DImode instructions.
224 ;; -------------------------------------------------------------
226 ;; Nowadays, the generic code is supposed to split the DImode
227 ;; boolean operations and have good code generation.
228 ;; Unless we find out some bad cases, there is no need to
229 ;; define DImode boolean operations by ourself.
231 ;; -------------------------------------------------------------