arm-fixed.md revision 1.3.4.2 1 1.3.4.2 martin ;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
2 1.1 mrg ;;
3 1.1 mrg ;; This file is part of GCC.
4 1.1 mrg ;;
5 1.1 mrg ;; GCC is free software; you can redistribute it and/or modify it
6 1.1 mrg ;; under the terms of the GNU General Public License as published
7 1.1 mrg ;; by the Free Software Foundation; either version 3, or (at your
8 1.1 mrg ;; option) any later version.
9 1.1 mrg ;;
10 1.1 mrg ;; GCC is distributed in the hope that it will be useful, but WITHOUT
11 1.1 mrg ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 1.1 mrg ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 1.1 mrg ;; License for more details.
14 1.1 mrg ;;
15 1.1 mrg ;; You should have received a copy of the GNU General Public License
16 1.1 mrg ;; along with GCC; see the file COPYING3. If not see
17 1.1 mrg ;; <http://www.gnu.org/licenses/>.
18 1.1 mrg ;;
19 1.1 mrg ;; This file contains ARM instructions that support fixed-point operations.
20 1.1 mrg
21 1.1 mrg (define_insn "add<mode>3"
22 1.3 mrg [(set (match_operand:FIXED 0 "s_register_operand" "=l,r")
23 1.3 mrg (plus:FIXED (match_operand:FIXED 1 "s_register_operand" "l,r")
24 1.3 mrg (match_operand:FIXED 2 "s_register_operand" "l,r")))]
25 1.1 mrg "TARGET_32BIT"
26 1.1 mrg "add%?\\t%0, %1, %2"
27 1.3 mrg [(set_attr "predicable" "yes")
28 1.3 mrg (set_attr "predicable_short_it" "yes,no")
29 1.3 mrg (set_attr "type" "alu_sreg")])
30 1.1 mrg
31 1.1 mrg (define_insn "add<mode>3"
32 1.1 mrg [(set (match_operand:ADDSUB 0 "s_register_operand" "=r")
33 1.1 mrg (plus:ADDSUB (match_operand:ADDSUB 1 "s_register_operand" "r")
34 1.1 mrg (match_operand:ADDSUB 2 "s_register_operand" "r")))]
35 1.1 mrg "TARGET_INT_SIMD"
36 1.1 mrg "sadd<qaddsub_suf>%?\\t%0, %1, %2"
37 1.3 mrg [(set_attr "predicable" "yes")
38 1.3 mrg (set_attr "predicable_short_it" "no")
39 1.3 mrg (set_attr "type" "alu_dsp_reg")])
40 1.1 mrg
41 1.1 mrg (define_insn "usadd<mode>3"
42 1.1 mrg [(set (match_operand:UQADDSUB 0 "s_register_operand" "=r")
43 1.1 mrg (us_plus:UQADDSUB (match_operand:UQADDSUB 1 "s_register_operand" "r")
44 1.1 mrg (match_operand:UQADDSUB 2 "s_register_operand" "r")))]
45 1.1 mrg "TARGET_INT_SIMD"
46 1.1 mrg "uqadd<qaddsub_suf>%?\\t%0, %1, %2"
47 1.3 mrg [(set_attr "predicable" "yes")
48 1.3 mrg (set_attr "predicable_short_it" "no")
49 1.3 mrg (set_attr "type" "alu_dsp_reg")])
50 1.1 mrg
51 1.1 mrg (define_insn "ssadd<mode>3"
52 1.1 mrg [(set (match_operand:QADDSUB 0 "s_register_operand" "=r")
53 1.1 mrg (ss_plus:QADDSUB (match_operand:QADDSUB 1 "s_register_operand" "r")
54 1.1 mrg (match_operand:QADDSUB 2 "s_register_operand" "r")))]
55 1.1 mrg "TARGET_INT_SIMD"
56 1.1 mrg "qadd<qaddsub_suf>%?\\t%0, %1, %2"
57 1.3 mrg [(set_attr "predicable" "yes")
58 1.3 mrg (set_attr "predicable_short_it" "no")
59 1.3 mrg (set_attr "type" "alu_dsp_reg")])
60 1.1 mrg
61 1.1 mrg (define_insn "sub<mode>3"
62 1.3 mrg [(set (match_operand:FIXED 0 "s_register_operand" "=l,r")
63 1.3 mrg (minus:FIXED (match_operand:FIXED 1 "s_register_operand" "l,r")
64 1.3 mrg (match_operand:FIXED 2 "s_register_operand" "l,r")))]
65 1.1 mrg "TARGET_32BIT"
66 1.1 mrg "sub%?\\t%0, %1, %2"
67 1.3 mrg [(set_attr "predicable" "yes")
68 1.3 mrg (set_attr "predicable_short_it" "yes,no")
69 1.3 mrg (set_attr "type" "alu_sreg")])
70 1.1 mrg
71 1.1 mrg (define_insn "sub<mode>3"
72 1.1 mrg [(set (match_operand:ADDSUB 0 "s_register_operand" "=r")
73 1.1 mrg (minus:ADDSUB (match_operand:ADDSUB 1 "s_register_operand" "r")
74 1.1 mrg (match_operand:ADDSUB 2 "s_register_operand" "r")))]
75 1.1 mrg "TARGET_INT_SIMD"
76 1.1 mrg "ssub<qaddsub_suf>%?\\t%0, %1, %2"
77 1.3 mrg [(set_attr "predicable" "yes")
78 1.3 mrg (set_attr "predicable_short_it" "no")
79 1.3 mrg (set_attr "type" "alu_dsp_reg")])
80 1.1 mrg
81 1.1 mrg (define_insn "ussub<mode>3"
82 1.1 mrg [(set (match_operand:UQADDSUB 0 "s_register_operand" "=r")
83 1.1 mrg (us_minus:UQADDSUB
84 1.1 mrg (match_operand:UQADDSUB 1 "s_register_operand" "r")
85 1.1 mrg (match_operand:UQADDSUB 2 "s_register_operand" "r")))]
86 1.1 mrg "TARGET_INT_SIMD"
87 1.1 mrg "uqsub<qaddsub_suf>%?\\t%0, %1, %2"
88 1.3 mrg [(set_attr "predicable" "yes")
89 1.3 mrg (set_attr "predicable_short_it" "no")
90 1.3 mrg (set_attr "type" "alu_dsp_reg")])
91 1.1 mrg
92 1.1 mrg (define_insn "sssub<mode>3"
93 1.1 mrg [(set (match_operand:QADDSUB 0 "s_register_operand" "=r")
94 1.1 mrg (ss_minus:QADDSUB (match_operand:QADDSUB 1 "s_register_operand" "r")
95 1.1 mrg (match_operand:QADDSUB 2 "s_register_operand" "r")))]
96 1.1 mrg "TARGET_INT_SIMD"
97 1.1 mrg "qsub<qaddsub_suf>%?\\t%0, %1, %2"
98 1.3 mrg [(set_attr "predicable" "yes")
99 1.3 mrg (set_attr "predicable_short_it" "no")
100 1.3 mrg (set_attr "type" "alu_dsp_reg")])
101 1.1 mrg
102 1.1 mrg ;; Fractional multiplies.
103 1.1 mrg
104 1.1 mrg ; Note: none of these do any rounding.
105 1.1 mrg
106 1.1 mrg (define_expand "mulqq3"
107 1.1 mrg [(set (match_operand:QQ 0 "s_register_operand" "")
108 1.1 mrg (mult:QQ (match_operand:QQ 1 "s_register_operand" "")
109 1.1 mrg (match_operand:QQ 2 "s_register_operand" "")))]
110 1.1 mrg "TARGET_DSP_MULTIPLY && arm_arch_thumb2"
111 1.1 mrg {
112 1.1 mrg rtx tmp1 = gen_reg_rtx (HImode);
113 1.1 mrg rtx tmp2 = gen_reg_rtx (HImode);
114 1.1 mrg rtx tmp3 = gen_reg_rtx (SImode);
115 1.3 mrg
116 1.1 mrg emit_insn (gen_extendqihi2 (tmp1, gen_lowpart (QImode, operands[1])));
117 1.1 mrg emit_insn (gen_extendqihi2 (tmp2, gen_lowpart (QImode, operands[2])));
118 1.1 mrg emit_insn (gen_mulhisi3 (tmp3, tmp1, tmp2));
119 1.1 mrg emit_insn (gen_extv (gen_lowpart (SImode, operands[0]), tmp3, GEN_INT (8),
120 1.1 mrg GEN_INT (7)));
121 1.1 mrg DONE;
122 1.1 mrg })
123 1.1 mrg
124 1.1 mrg (define_expand "mulhq3"
125 1.1 mrg [(set (match_operand:HQ 0 "s_register_operand" "")
126 1.1 mrg (mult:HQ (match_operand:HQ 1 "s_register_operand" "")
127 1.1 mrg (match_operand:HQ 2 "s_register_operand" "")))]
128 1.1 mrg "TARGET_DSP_MULTIPLY && arm_arch_thumb2"
129 1.1 mrg {
130 1.1 mrg rtx tmp = gen_reg_rtx (SImode);
131 1.1 mrg
132 1.1 mrg emit_insn (gen_mulhisi3 (tmp, gen_lowpart (HImode, operands[1]),
133 1.1 mrg gen_lowpart (HImode, operands[2])));
134 1.1 mrg /* We're doing a s.15 * s.15 multiplication, getting an s.30 result. Extract
135 1.1 mrg an s.15 value from that. This won't overflow/saturate for _Fract
136 1.1 mrg values. */
137 1.1 mrg emit_insn (gen_extv (gen_lowpart (SImode, operands[0]), tmp,
138 1.1 mrg GEN_INT (16), GEN_INT (15)));
139 1.1 mrg DONE;
140 1.1 mrg })
141 1.1 mrg
142 1.1 mrg (define_expand "mulsq3"
143 1.1 mrg [(set (match_operand:SQ 0 "s_register_operand" "")
144 1.1 mrg (mult:SQ (match_operand:SQ 1 "s_register_operand" "")
145 1.1 mrg (match_operand:SQ 2 "s_register_operand" "")))]
146 1.1 mrg "TARGET_32BIT && arm_arch3m"
147 1.1 mrg {
148 1.1 mrg rtx tmp1 = gen_reg_rtx (DImode);
149 1.1 mrg rtx tmp2 = gen_reg_rtx (SImode);
150 1.1 mrg rtx tmp3 = gen_reg_rtx (SImode);
151 1.3 mrg
152 1.1 mrg /* s.31 * s.31 -> s.62 multiplication. */
153 1.1 mrg emit_insn (gen_mulsidi3 (tmp1, gen_lowpart (SImode, operands[1]),
154 1.1 mrg gen_lowpart (SImode, operands[2])));
155 1.1 mrg emit_insn (gen_lshrsi3 (tmp2, gen_lowpart (SImode, tmp1), GEN_INT (31)));
156 1.1 mrg emit_insn (gen_ashlsi3 (tmp3, gen_highpart (SImode, tmp1), GEN_INT (1)));
157 1.1 mrg emit_insn (gen_iorsi3 (gen_lowpart (SImode, operands[0]), tmp2, tmp3));
158 1.1 mrg
159 1.1 mrg DONE;
160 1.1 mrg })
161 1.1 mrg
162 1.1 mrg ;; Accumulator multiplies.
163 1.1 mrg
164 1.1 mrg (define_expand "mulsa3"
165 1.1 mrg [(set (match_operand:SA 0 "s_register_operand" "")
166 1.1 mrg (mult:SA (match_operand:SA 1 "s_register_operand" "")
167 1.1 mrg (match_operand:SA 2 "s_register_operand" "")))]
168 1.1 mrg "TARGET_32BIT && arm_arch3m"
169 1.1 mrg {
170 1.1 mrg rtx tmp1 = gen_reg_rtx (DImode);
171 1.1 mrg rtx tmp2 = gen_reg_rtx (SImode);
172 1.1 mrg rtx tmp3 = gen_reg_rtx (SImode);
173 1.3 mrg
174 1.1 mrg emit_insn (gen_mulsidi3 (tmp1, gen_lowpart (SImode, operands[1]),
175 1.1 mrg gen_lowpart (SImode, operands[2])));
176 1.1 mrg emit_insn (gen_lshrsi3 (tmp2, gen_lowpart (SImode, tmp1), GEN_INT (15)));
177 1.1 mrg emit_insn (gen_ashlsi3 (tmp3, gen_highpart (SImode, tmp1), GEN_INT (17)));
178 1.1 mrg emit_insn (gen_iorsi3 (gen_lowpart (SImode, operands[0]), tmp2, tmp3));
179 1.1 mrg
180 1.1 mrg DONE;
181 1.1 mrg })
182 1.1 mrg
183 1.1 mrg (define_expand "mulusa3"
184 1.1 mrg [(set (match_operand:USA 0 "s_register_operand" "")
185 1.1 mrg (mult:USA (match_operand:USA 1 "s_register_operand" "")
186 1.1 mrg (match_operand:USA 2 "s_register_operand" "")))]
187 1.1 mrg "TARGET_32BIT && arm_arch3m"
188 1.1 mrg {
189 1.1 mrg rtx tmp1 = gen_reg_rtx (DImode);
190 1.1 mrg rtx tmp2 = gen_reg_rtx (SImode);
191 1.1 mrg rtx tmp3 = gen_reg_rtx (SImode);
192 1.3 mrg
193 1.1 mrg emit_insn (gen_umulsidi3 (tmp1, gen_lowpart (SImode, operands[1]),
194 1.1 mrg gen_lowpart (SImode, operands[2])));
195 1.1 mrg emit_insn (gen_lshrsi3 (tmp2, gen_lowpart (SImode, tmp1), GEN_INT (16)));
196 1.1 mrg emit_insn (gen_ashlsi3 (tmp3, gen_highpart (SImode, tmp1), GEN_INT (16)));
197 1.1 mrg emit_insn (gen_iorsi3 (gen_lowpart (SImode, operands[0]), tmp2, tmp3));
198 1.3 mrg
199 1.1 mrg DONE;
200 1.1 mrg })
201 1.1 mrg
202 1.1 mrg ;; The code sequence emitted by this insn pattern uses the Q flag, which GCC
203 1.1 mrg ;; doesn't generally know about, so we don't bother expanding to individual
204 1.1 mrg ;; instructions. It may be better to just use an out-of-line asm libcall for
205 1.1 mrg ;; this.
206 1.1 mrg
207 1.1 mrg (define_insn "ssmulsa3"
208 1.1 mrg [(set (match_operand:SA 0 "s_register_operand" "=r")
209 1.1 mrg (ss_mult:SA (match_operand:SA 1 "s_register_operand" "r")
210 1.1 mrg (match_operand:SA 2 "s_register_operand" "r")))
211 1.1 mrg (clobber (match_scratch:DI 3 "=r"))
212 1.1 mrg (clobber (match_scratch:SI 4 "=r"))
213 1.1 mrg (clobber (reg:CC CC_REGNUM))]
214 1.1 mrg "TARGET_32BIT && arm_arch6"
215 1.1 mrg {
216 1.1 mrg /* s16.15 * s16.15 -> s32.30. */
217 1.1 mrg output_asm_insn ("smull\\t%Q3, %R3, %1, %2", operands);
218 1.1 mrg
219 1.1 mrg if (TARGET_ARM)
220 1.1 mrg output_asm_insn ("msr\\tAPSR_nzcvq, #0", operands);
221 1.1 mrg else
222 1.1 mrg {
223 1.1 mrg output_asm_insn ("mov\\t%4, #0", operands);
224 1.1 mrg output_asm_insn ("msr\\tAPSR_nzcvq, %4", operands);
225 1.1 mrg }
226 1.1 mrg
227 1.1 mrg /* We have:
228 1.3 mrg 31 high word 0 31 low word 0
229 1.1 mrg
230 1.1 mrg [ S i i .... i i i ] [ i f f f ... f f ]
231 1.1 mrg |
232 1.1 mrg v
233 1.1 mrg [ S i ... i f ... f f ]
234 1.1 mrg
235 1.1 mrg Need 16 integral bits, so saturate at 15th bit of high word. */
236 1.1 mrg
237 1.1 mrg output_asm_insn ("ssat\\t%R3, #15, %R3", operands);
238 1.1 mrg output_asm_insn ("mrs\\t%4, APSR", operands);
239 1.1 mrg output_asm_insn ("tst\\t%4, #1<<27", operands);
240 1.3 mrg if (arm_restrict_it)
241 1.3 mrg {
242 1.3 mrg output_asm_insn ("mvn\\t%4, %R3, asr #32", operands);
243 1.3 mrg output_asm_insn ("it\\tne", operands);
244 1.3 mrg output_asm_insn ("movne\\t%Q3, %4", operands);
245 1.3 mrg }
246 1.3 mrg else
247 1.3 mrg {
248 1.3 mrg if (TARGET_THUMB2)
249 1.3 mrg output_asm_insn ("it\\tne", operands);
250 1.3 mrg output_asm_insn ("mvnne\\t%Q3, %R3, asr #32", operands);
251 1.3 mrg }
252 1.1 mrg output_asm_insn ("mov\\t%0, %Q3, lsr #15", operands);
253 1.1 mrg output_asm_insn ("orr\\t%0, %0, %R3, asl #17", operands);
254 1.1 mrg return "";
255 1.1 mrg }
256 1.1 mrg [(set_attr "conds" "clob")
257 1.3 mrg (set_attr "type" "multiple")
258 1.1 mrg (set (attr "length")
259 1.1 mrg (if_then_else (eq_attr "is_thumb" "yes")
260 1.3 mrg (if_then_else (match_test "arm_restrict_it")
261 1.3 mrg (const_int 40)
262 1.3 mrg (const_int 38))
263 1.1 mrg (const_int 32)))])
264 1.1 mrg
265 1.1 mrg ;; Same goes for this.
266 1.1 mrg
267 1.1 mrg (define_insn "usmulusa3"
268 1.1 mrg [(set (match_operand:USA 0 "s_register_operand" "=r")
269 1.1 mrg (us_mult:USA (match_operand:USA 1 "s_register_operand" "r")
270 1.1 mrg (match_operand:USA 2 "s_register_operand" "r")))
271 1.1 mrg (clobber (match_scratch:DI 3 "=r"))
272 1.1 mrg (clobber (match_scratch:SI 4 "=r"))
273 1.1 mrg (clobber (reg:CC CC_REGNUM))]
274 1.1 mrg "TARGET_32BIT && arm_arch6"
275 1.1 mrg {
276 1.1 mrg /* 16.16 * 16.16 -> 32.32. */
277 1.1 mrg output_asm_insn ("umull\\t%Q3, %R3, %1, %2", operands);
278 1.1 mrg
279 1.1 mrg if (TARGET_ARM)
280 1.1 mrg output_asm_insn ("msr\\tAPSR_nzcvq, #0", operands);
281 1.1 mrg else
282 1.1 mrg {
283 1.1 mrg output_asm_insn ("mov\\t%4, #0", operands);
284 1.1 mrg output_asm_insn ("msr\\tAPSR_nzcvq, %4", operands);
285 1.1 mrg }
286 1.1 mrg
287 1.1 mrg /* We have:
288 1.3 mrg 31 high word 0 31 low word 0
289 1.1 mrg
290 1.1 mrg [ i i i .... i i i ] [ f f f f ... f f ]
291 1.1 mrg |
292 1.1 mrg v
293 1.1 mrg [ i i ... i f ... f f ]
294 1.1 mrg
295 1.1 mrg Need 16 integral bits, so saturate at 16th bit of high word. */
296 1.1 mrg
297 1.1 mrg output_asm_insn ("usat\\t%R3, #16, %R3", operands);
298 1.1 mrg output_asm_insn ("mrs\\t%4, APSR", operands);
299 1.1 mrg output_asm_insn ("tst\\t%4, #1<<27", operands);
300 1.3 mrg if (arm_restrict_it)
301 1.3 mrg {
302 1.3 mrg output_asm_insn ("sbfx\\t%4, %R3, #15, #1", operands);
303 1.3 mrg output_asm_insn ("it\\tne", operands);
304 1.3 mrg output_asm_insn ("movne\\t%Q3, %4", operands);
305 1.3 mrg }
306 1.3 mrg else
307 1.3 mrg {
308 1.3 mrg if (TARGET_THUMB2)
309 1.3 mrg output_asm_insn ("it\\tne", operands);
310 1.3 mrg output_asm_insn ("sbfxne\\t%Q3, %R3, #15, #1", operands);
311 1.3 mrg }
312 1.1 mrg output_asm_insn ("lsr\\t%0, %Q3, #16", operands);
313 1.1 mrg output_asm_insn ("orr\\t%0, %0, %R3, asl #16", operands);
314 1.1 mrg return "";
315 1.1 mrg }
316 1.1 mrg [(set_attr "conds" "clob")
317 1.3 mrg (set_attr "type" "multiple")
318 1.1 mrg (set (attr "length")
319 1.1 mrg (if_then_else (eq_attr "is_thumb" "yes")
320 1.3 mrg (if_then_else (match_test "arm_restrict_it")
321 1.3 mrg (const_int 40)
322 1.3 mrg (const_int 38))
323 1.1 mrg (const_int 32)))])
324 1.1 mrg
325 1.1 mrg (define_expand "mulha3"
326 1.1 mrg [(set (match_operand:HA 0 "s_register_operand" "")
327 1.1 mrg (mult:HA (match_operand:HA 1 "s_register_operand" "")
328 1.1 mrg (match_operand:HA 2 "s_register_operand" "")))]
329 1.1 mrg "TARGET_DSP_MULTIPLY && arm_arch_thumb2"
330 1.1 mrg {
331 1.1 mrg rtx tmp = gen_reg_rtx (SImode);
332 1.3 mrg
333 1.1 mrg emit_insn (gen_mulhisi3 (tmp, gen_lowpart (HImode, operands[1]),
334 1.1 mrg gen_lowpart (HImode, operands[2])));
335 1.1 mrg emit_insn (gen_extv (gen_lowpart (SImode, operands[0]), tmp, GEN_INT (16),
336 1.1 mrg GEN_INT (7)));
337 1.1 mrg
338 1.1 mrg DONE;
339 1.1 mrg })
340 1.1 mrg
341 1.1 mrg (define_expand "muluha3"
342 1.1 mrg [(set (match_operand:UHA 0 "s_register_operand" "")
343 1.1 mrg (mult:UHA (match_operand:UHA 1 "s_register_operand" "")
344 1.1 mrg (match_operand:UHA 2 "s_register_operand" "")))]
345 1.1 mrg "TARGET_DSP_MULTIPLY"
346 1.1 mrg {
347 1.1 mrg rtx tmp1 = gen_reg_rtx (SImode);
348 1.1 mrg rtx tmp2 = gen_reg_rtx (SImode);
349 1.1 mrg rtx tmp3 = gen_reg_rtx (SImode);
350 1.3 mrg
351 1.1 mrg /* 8.8 * 8.8 -> 16.16 multiply. */
352 1.1 mrg emit_insn (gen_zero_extendhisi2 (tmp1, gen_lowpart (HImode, operands[1])));
353 1.1 mrg emit_insn (gen_zero_extendhisi2 (tmp2, gen_lowpart (HImode, operands[2])));
354 1.1 mrg emit_insn (gen_mulsi3 (tmp3, tmp1, tmp2));
355 1.1 mrg emit_insn (gen_extzv (gen_lowpart (SImode, operands[0]), tmp3,
356 1.1 mrg GEN_INT (16), GEN_INT (8)));
357 1.1 mrg
358 1.1 mrg DONE;
359 1.1 mrg })
360 1.1 mrg
361 1.1 mrg (define_expand "ssmulha3"
362 1.1 mrg [(set (match_operand:HA 0 "s_register_operand" "")
363 1.1 mrg (ss_mult:HA (match_operand:HA 1 "s_register_operand" "")
364 1.1 mrg (match_operand:HA 2 "s_register_operand" "")))]
365 1.1 mrg "TARGET_32BIT && TARGET_DSP_MULTIPLY && arm_arch6"
366 1.1 mrg {
367 1.1 mrg rtx tmp = gen_reg_rtx (SImode);
368 1.1 mrg rtx rshift;
369 1.3 mrg
370 1.1 mrg emit_insn (gen_mulhisi3 (tmp, gen_lowpart (HImode, operands[1]),
371 1.1 mrg gen_lowpart (HImode, operands[2])));
372 1.1 mrg
373 1.1 mrg rshift = gen_rtx_ASHIFTRT (SImode, tmp, GEN_INT (7));
374 1.1 mrg
375 1.3.4.1 christos emit_insn (gen_rtx_SET (gen_lowpart (HImode, operands[0]),
376 1.1 mrg gen_rtx_SS_TRUNCATE (HImode, rshift)));
377 1.1 mrg
378 1.1 mrg DONE;
379 1.1 mrg })
380 1.1 mrg
381 1.1 mrg (define_expand "usmuluha3"
382 1.1 mrg [(set (match_operand:UHA 0 "s_register_operand" "")
383 1.1 mrg (us_mult:UHA (match_operand:UHA 1 "s_register_operand" "")
384 1.1 mrg (match_operand:UHA 2 "s_register_operand" "")))]
385 1.1 mrg "TARGET_INT_SIMD"
386 1.1 mrg {
387 1.1 mrg rtx tmp1 = gen_reg_rtx (SImode);
388 1.1 mrg rtx tmp2 = gen_reg_rtx (SImode);
389 1.1 mrg rtx tmp3 = gen_reg_rtx (SImode);
390 1.1 mrg rtx rshift_tmp = gen_reg_rtx (SImode);
391 1.3 mrg
392 1.1 mrg /* Note: there's no smul[bt][bt] equivalent for unsigned multiplies. Use a
393 1.1 mrg normal 32x32->32-bit multiply instead. */
394 1.1 mrg emit_insn (gen_zero_extendhisi2 (tmp1, gen_lowpart (HImode, operands[1])));
395 1.1 mrg emit_insn (gen_zero_extendhisi2 (tmp2, gen_lowpart (HImode, operands[2])));
396 1.3 mrg
397 1.1 mrg emit_insn (gen_mulsi3 (tmp3, tmp1, tmp2));
398 1.1 mrg
399 1.1 mrg /* The operand to "usat" is signed, so we cannot use the "..., asr #8"
400 1.1 mrg form of that instruction since the multiplication result TMP3 may have the
401 1.1 mrg top bit set, thus be negative and saturate to zero. Use a separate
402 1.1 mrg logical right-shift instead. */
403 1.1 mrg emit_insn (gen_lshrsi3 (rshift_tmp, tmp3, GEN_INT (8)));
404 1.1 mrg emit_insn (gen_arm_usatsihi (gen_lowpart (HImode, operands[0]), rshift_tmp));
405 1.1 mrg
406 1.1 mrg DONE;
407 1.1 mrg })
408 1.1 mrg
409 1.1 mrg (define_insn "arm_ssatsihi_shift"
410 1.1 mrg [(set (match_operand:HI 0 "s_register_operand" "=r")
411 1.1 mrg (ss_truncate:HI (match_operator:SI 1 "sat_shift_operator"
412 1.1 mrg [(match_operand:SI 2 "s_register_operand" "r")
413 1.1 mrg (match_operand:SI 3 "immediate_operand" "I")])))]
414 1.1 mrg "TARGET_32BIT && arm_arch6"
415 1.1 mrg "ssat%?\\t%0, #16, %2%S1"
416 1.1 mrg [(set_attr "predicable" "yes")
417 1.3 mrg (set_attr "predicable_short_it" "no")
418 1.1 mrg (set_attr "shift" "1")
419 1.3 mrg (set_attr "type" "alu_shift_imm")])
420 1.1 mrg
421 1.1 mrg (define_insn "arm_usatsihi"
422 1.1 mrg [(set (match_operand:HI 0 "s_register_operand" "=r")
423 1.1 mrg (us_truncate:HI (match_operand:SI 1 "s_register_operand")))]
424 1.1 mrg "TARGET_INT_SIMD"
425 1.1 mrg "usat%?\\t%0, #16, %1"
426 1.1 mrg [(set_attr "predicable" "yes")
427 1.3 mrg (set_attr "predicable_short_it" "no")
428 1.3 mrg (set_attr "type" "alu_imm")]
429 1.3 mrg )
430