111
|
1 ;; DImode/DFmode patterns description of Andes NDS32 cpu for GNU compiler
|
131
|
2 ;; Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
111
|
3 ;; Contributed by Andes Technology Corporation.
|
|
4 ;;
|
|
5 ;; This file is part of GCC.
|
|
6 ;;
|
|
7 ;; GCC is free software; you can redistribute it and/or modify it
|
|
8 ;; under the terms of the GNU General Public License as published
|
|
9 ;; by the Free Software Foundation; either version 3, or (at your
|
|
10 ;; option) any later version.
|
|
11 ;;
|
|
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
|
|
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
14 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
15 ;; License for more details.
|
|
16 ;;
|
|
17 ;; You should have received a copy of the GNU General Public License
|
|
18 ;; along with GCC; see the file COPYING3. If not see
|
|
19 ;; <http://www.gnu.org/licenses/>.
|
|
20
|
|
21
|
|
22 ;; -------------------------------------------------------------
|
|
23 ;; Move DImode/DFmode instructions.
|
|
24 ;; -------------------------------------------------------------
|
|
25
|
|
26
|
|
27 (define_expand "movdi"
|
|
28 [(set (match_operand:DI 0 "general_operand" "")
|
|
29 (match_operand:DI 1 "general_operand" ""))]
|
|
30 ""
|
|
31 {
|
|
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]);
|
|
35 })
|
|
36
|
|
37 (define_expand "movdf"
|
|
38 [(set (match_operand:DF 0 "general_operand" "")
|
|
39 (match_operand:DF 1 "general_operand" ""))]
|
|
40 ""
|
|
41 {
|
|
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]);
|
|
45 })
|
|
46
|
|
47
|
|
48 (define_insn "move_<mode>"
|
131
|
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)"
|
111
|
53 {
|
|
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:
|
131
|
62 /* The memory format is (mem (reg)),
|
|
63 we can generate 'lmw.bi' instruction. */
|
|
64 return nds32_output_double (operands, true);
|
111
|
65 case 3:
|
131
|
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";
|
111
|
87 default:
|
|
88 gcc_unreachable ();
|
|
89 }
|
|
90 }
|
131
|
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")])
|
|
120
|
|
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 }
|
|
137 )
|
111
|
138
|
|
139 (define_split
|
|
140 [(set (match_operand:DIDF 0 "register_operand" "")
|
|
141 (match_operand:DIDF 1 "const_double_operand" ""))]
|
131
|
142 "flag_pic || reload_completed"
|
111
|
143 [(set (match_dup 2) (match_dup 3))
|
|
144 (set (match_dup 4) (match_dup 5))]
|
|
145 {
|
|
146 /* Construct lowpart rtx. */
|
|
147 operands[2] = gen_lowpart (SImode, operands[0]);
|
|
148 operands[3] = gen_lowpart (SImode, operands[1]);
|
|
149
|
|
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]);
|
|
157
|
|
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]);
|
131
|
161
|
|
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]);
|
111
|
167 DONE;
|
|
168 })
|
|
169
|
|
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
|
131
|
176 && (TARGET_ISA_V2 || !TARGET_16_BIT)
|
|
177 && NDS32_IS_GPR_REGNUM (REGNO (operands[0]))
|
|
178 && NDS32_IS_GPR_REGNUM (REGNO (operands[1]))"
|
111
|
179 [(set (match_dup 0) (match_dup 1))
|
|
180 (set (match_dup 2) (match_dup 3))]
|
|
181 {
|
|
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]);
|
|
186
|
|
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];
|
|
192
|
|
193 operands[0] = operands[2];
|
|
194 operands[1] = operands[3];
|
|
195 operands[2] = tmp0;
|
|
196 operands[3] = tmp1;
|
|
197 }
|
|
198 })
|
|
199
|
131
|
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))]
|
|
207 {
|
|
208 nds32_spilt_doubleword (operands, true);
|
|
209 })
|
|
210
|
|
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))]
|
|
218 {
|
|
219 nds32_spilt_doubleword (operands, false);
|
|
220 })
|
|
221
|
111
|
222 ;; -------------------------------------------------------------
|
|
223 ;; Boolean DImode instructions.
|
|
224 ;; -------------------------------------------------------------
|
|
225
|
|
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.
|
|
230
|
|
231 ;; -------------------------------------------------------------
|