]>
Commit | Line | Data |
---|---|---|
03984308 | 1 | ;; GCC machine description for Tensilica's Xtensa architecture. |
b86dee19 | 2 | ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 |
09fa8841 | 3 | ;; Free Software Foundation, Inc. |
03984308 BW |
4 | ;; Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. |
5 | ||
6 | ;; This file is part of GCC. | |
7 | ||
8 | ;; GCC is free software; you can redistribute it and/or modify it | |
9 | ;; under the terms of the GNU General Public License as published by | |
2f83c7d6 | 10 | ;; the Free Software Foundation; either version 3, or (at your option) |
03984308 BW |
11 | ;; any later version. |
12 | ||
13 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT | |
14 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
15 | ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
16 | ;; License for more details. | |
17 | ||
18 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
19 | ;; along with GCC; see the file COPYING3. If not see |
20 | ;; <http://www.gnu.org/licenses/>. | |
03984308 | 21 | |
03984308 BW |
22 | |
23 | (define_constants [ | |
24 | (A0_REG 0) | |
f42f5a1b | 25 | (A1_REG 1) |
03984308 | 26 | (A7_REG 7) |
f42f5a1b | 27 | (A8_REG 8) |
03984308 | 28 | |
03984308 BW |
29 | (UNSPEC_NOP 2) |
30 | (UNSPEC_PLT 3) | |
0c14a54d | 31 | (UNSPEC_RET_ADDR 4) |
2a48b790 | 32 | |
03984308 | 33 | (UNSPECV_SET_FP 1) |
f42f5a1b | 34 | (UNSPECV_ENTRY 2) |
2a48b790 BW |
35 | (UNSPECV_MEMW 3) |
36 | (UNSPECV_S32RI 4) | |
37 | (UNSPECV_S32C1I 5) | |
03984308 BW |
38 | ]) |
39 | ||
09fa8841 BW |
40 | ;; This code macro allows signed and unsigned widening multiplications |
41 | ;; to use the same template. | |
42 | (define_code_macro any_extend [sign_extend zero_extend]) | |
43 | ||
44 | ;; <u> expands to an empty string when doing a signed operation and | |
45 | ;; "u" when doing an unsigned operation. | |
46 | (define_code_attr u [(sign_extend "") (zero_extend "u")]) | |
47 | ||
48 | ;; <su> is like <u>, but the signed form expands to "s" rather than "". | |
49 | (define_code_attr su [(sign_extend "s") (zero_extend "u")]) | |
50 | ||
036a2b7a BW |
51 | ;; This code macro allows four integer min/max operations to be |
52 | ;; generated from one template. | |
53 | (define_code_macro any_minmax [smin umin smax umax]) | |
54 | ||
55 | ;; <minmax> expands to the opcode name for any_minmax operations. | |
56 | (define_code_attr minmax [(smin "min") (umin "minu") | |
57 | (smax "max") (umax "maxu")]) | |
58 | ||
59 | ;; This code macro allows all branch instructions to be generated from | |
60 | ;; a single define_expand template. | |
61 | (define_code_macro any_cond [eq ne gt ge lt le gtu geu ltu leu]) | |
62 | ||
63 | ;; This code macro is for setting a register from a comparison. | |
64 | (define_code_macro any_scc [eq ne gt ge lt le]) | |
65 | ||
66 | ;; This code macro is for floating-point comparisons. | |
67 | (define_code_macro any_scc_sf [eq lt le]) | |
68 | ||
2a48b790 BW |
69 | ;; These macros allow to combine most atomic operations. |
70 | (define_code_macro ATOMIC [and ior xor plus minus mult]) | |
71 | (define_code_attr atomic [(and "and") (ior "ior") (xor "xor") | |
72 | (plus "add") (minus "sub") (mult "nand")]) | |
73 | ||
74 | ;; These mode macros allow the HI and QI patterns to be defined from | |
75 | ;; the same template. | |
76 | (define_mode_macro HQI [HI QI]) | |
77 | ||
13fb3a61 BW |
78 | \f |
79 | ;; Attributes. | |
03984308 BW |
80 | |
81 | (define_attr "type" | |
3a307de4 | 82 | "unknown,jump,call,load,store,move,arith,multi,nop,farith,fmadd,fdiv,fsqrt,fconv,fload,fstore,mul16,mul32,div32,mac16,rsr,wsr" |
03984308 BW |
83 | (const_string "unknown")) |
84 | ||
85 | (define_attr "mode" | |
86 | "unknown,none,QI,HI,SI,DI,SF,DF,BL" | |
87 | (const_string "unknown")) | |
88 | ||
89 | (define_attr "length" "" (const_int 1)) | |
90 | ||
91 | ;; Describe a user's asm statement. | |
92 | (define_asm_attributes | |
93 | [(set_attr "type" "multi")]) | |
94 | ||
13fb3a61 | 95 | \f |
3b1cce6a | 96 | ;; Pipeline model. |
03984308 | 97 | |
3b1cce6a SB |
98 | ;; The Xtensa basically has simple 5-stage RISC pipeline. |
99 | ;; Most instructions complete in 1 cycle, and it is OK to assume that | |
100 | ;; everything is fully pipelined. The exceptions have special insn | |
101 | ;; reservations in the pipeline description below. The Xtensa can | |
102 | ;; issue one instruction per cycle, so defining CPU units is unnecessary. | |
03984308 | 103 | |
3b1cce6a SB |
104 | (define_insn_reservation "xtensa_any_insn" 1 |
105 | (eq_attr "type" "!load,fload,rsr,mul16,mul32,fmadd,fconv") | |
106 | "nothing") | |
03984308 | 107 | |
3b1cce6a SB |
108 | (define_insn_reservation "xtensa_memory" 2 |
109 | (eq_attr "type" "load,fload") | |
110 | "nothing") | |
03984308 | 111 | |
3b1cce6a SB |
112 | (define_insn_reservation "xtensa_sreg" 2 |
113 | (eq_attr "type" "rsr") | |
114 | "nothing") | |
03984308 | 115 | |
3b1cce6a SB |
116 | (define_insn_reservation "xtensa_mul16" 2 |
117 | (eq_attr "type" "mul16") | |
118 | "nothing") | |
03984308 | 119 | |
3b1cce6a SB |
120 | (define_insn_reservation "xtensa_mul32" 2 |
121 | (eq_attr "type" "mul32") | |
122 | "nothing") | |
03984308 | 123 | |
3b1cce6a SB |
124 | (define_insn_reservation "xtensa_fmadd" 4 |
125 | (eq_attr "type" "fmadd") | |
126 | "nothing") | |
127 | ||
128 | (define_insn_reservation "xtensa_fconv" 2 | |
129 | (eq_attr "type" "fconv") | |
130 | "nothing") | |
8eb1bc5c | 131 | \f |
887af464 | 132 | ;; Include predicates and constraints. |
8eb1bc5c BW |
133 | |
134 | (include "predicates.md") | |
887af464 | 135 | (include "constraints.md") |
8eb1bc5c | 136 | |
13fb3a61 BW |
137 | \f |
138 | ;; Addition. | |
03984308 BW |
139 | |
140 | (define_insn "addsi3" | |
141 | [(set (match_operand:SI 0 "register_operand" "=D,D,a,a,a") | |
142 | (plus:SI (match_operand:SI 1 "register_operand" "%d,d,r,r,r") | |
143 | (match_operand:SI 2 "add_operand" "d,O,r,J,N")))] | |
144 | "" | |
145 | "@ | |
13fb3a61 BW |
146 | add.n\t%0, %1, %2 |
147 | addi.n\t%0, %1, %d2 | |
148 | add\t%0, %1, %2 | |
149 | addi\t%0, %1, %d2 | |
150 | addmi\t%0, %1, %x2" | |
03984308 BW |
151 | [(set_attr "type" "arith,arith,arith,arith,arith") |
152 | (set_attr "mode" "SI") | |
153 | (set_attr "length" "2,2,3,3,3")]) | |
154 | ||
036a2b7a | 155 | (define_insn "*addx" |
03984308 BW |
156 | [(set (match_operand:SI 0 "register_operand" "=a") |
157 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") | |
036a2b7a | 158 | (match_operand:SI 3 "addsubx_operand" "i")) |
03984308 | 159 | (match_operand:SI 2 "register_operand" "r")))] |
6c2e8d1c | 160 | "TARGET_ADDX" |
036a2b7a | 161 | "addx%3\t%0, %1, %2" |
03984308 BW |
162 | [(set_attr "type" "arith") |
163 | (set_attr "mode" "SI") | |
164 | (set_attr "length" "3")]) | |
165 | ||
166 | (define_insn "addsf3" | |
167 | [(set (match_operand:SF 0 "register_operand" "=f") | |
168 | (plus:SF (match_operand:SF 1 "register_operand" "%f") | |
169 | (match_operand:SF 2 "register_operand" "f")))] | |
170 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 171 | "add.s\t%0, %1, %2" |
03984308 BW |
172 | [(set_attr "type" "fmadd") |
173 | (set_attr "mode" "SF") | |
174 | (set_attr "length" "3")]) | |
175 | ||
13fb3a61 BW |
176 | \f |
177 | ;; Subtraction. | |
03984308 BW |
178 | |
179 | (define_insn "subsi3" | |
180 | [(set (match_operand:SI 0 "register_operand" "=a") | |
181 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
182 | (match_operand:SI 2 "register_operand" "r")))] | |
183 | "" | |
13fb3a61 | 184 | "sub\t%0, %1, %2" |
03984308 BW |
185 | [(set_attr "type" "arith") |
186 | (set_attr "mode" "SI") | |
187 | (set_attr "length" "3")]) | |
188 | ||
036a2b7a | 189 | (define_insn "*subx" |
03984308 BW |
190 | [(set (match_operand:SI 0 "register_operand" "=a") |
191 | (minus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") | |
036a2b7a | 192 | (match_operand:SI 3 "addsubx_operand" "i")) |
03984308 | 193 | (match_operand:SI 2 "register_operand" "r")))] |
6c2e8d1c | 194 | "TARGET_ADDX" |
036a2b7a | 195 | "subx%3\t%0, %1, %2" |
03984308 BW |
196 | [(set_attr "type" "arith") |
197 | (set_attr "mode" "SI") | |
198 | (set_attr "length" "3")]) | |
199 | ||
200 | (define_insn "subsf3" | |
201 | [(set (match_operand:SF 0 "register_operand" "=f") | |
202 | (minus:SF (match_operand:SF 1 "register_operand" "f") | |
203 | (match_operand:SF 2 "register_operand" "f")))] | |
204 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 205 | "sub.s\t%0, %1, %2" |
03984308 BW |
206 | [(set_attr "type" "fmadd") |
207 | (set_attr "mode" "SF") | |
208 | (set_attr "length" "3")]) | |
209 | ||
13fb3a61 BW |
210 | \f |
211 | ;; Multiplication. | |
03984308 | 212 | |
09fa8841 BW |
213 | (define_expand "<u>mulsidi3" |
214 | [(set (match_operand:DI 0 "register_operand") | |
215 | (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) | |
216 | (any_extend:DI (match_operand:SI 2 "register_operand"))))] | |
217 | "TARGET_MUL32_HIGH" | |
218 | { | |
219 | emit_insn (gen_mulsi3 (gen_lowpart (SImode, operands[0]), | |
220 | operands[1], operands[2])); | |
221 | emit_insn (gen_<u>mulsi3_highpart (gen_highpart (SImode, operands[0]), | |
222 | operands[1], operands[2])); | |
223 | DONE; | |
224 | }) | |
225 | ||
226 | (define_insn "<u>mulsi3_highpart" | |
227 | [(set (match_operand:SI 0 "register_operand" "=a") | |
228 | (truncate:SI | |
229 | (lshiftrt:DI | |
230 | (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "%r")) | |
231 | (any_extend:DI (match_operand:SI 2 "register_operand" "r"))) | |
232 | (const_int 32))))] | |
233 | "TARGET_MUL32_HIGH" | |
234 | "mul<su>h\t%0, %1, %2" | |
235 | [(set_attr "type" "mul32") | |
236 | (set_attr "mode" "SI") | |
237 | (set_attr "length" "3")]) | |
238 | ||
03984308 BW |
239 | (define_insn "mulsi3" |
240 | [(set (match_operand:SI 0 "register_operand" "=a") | |
241 | (mult:SI (match_operand:SI 1 "register_operand" "%r") | |
242 | (match_operand:SI 2 "register_operand" "r")))] | |
243 | "TARGET_MUL32" | |
13fb3a61 | 244 | "mull\t%0, %1, %2" |
03984308 BW |
245 | [(set_attr "type" "mul32") |
246 | (set_attr "mode" "SI") | |
247 | (set_attr "length" "3")]) | |
248 | ||
249 | (define_insn "mulhisi3" | |
250 | [(set (match_operand:SI 0 "register_operand" "=C,A") | |
251 | (mult:SI (sign_extend:SI | |
252 | (match_operand:HI 1 "register_operand" "%r,r")) | |
253 | (sign_extend:SI | |
254 | (match_operand:HI 2 "register_operand" "r,r"))))] | |
255 | "TARGET_MUL16 || TARGET_MAC16" | |
256 | "@ | |
13fb3a61 BW |
257 | mul16s\t%0, %1, %2 |
258 | mul.aa.ll\t%1, %2" | |
03984308 BW |
259 | [(set_attr "type" "mul16,mac16") |
260 | (set_attr "mode" "SI") | |
261 | (set_attr "length" "3,3")]) | |
262 | ||
263 | (define_insn "umulhisi3" | |
264 | [(set (match_operand:SI 0 "register_operand" "=C,A") | |
265 | (mult:SI (zero_extend:SI | |
266 | (match_operand:HI 1 "register_operand" "%r,r")) | |
267 | (zero_extend:SI | |
268 | (match_operand:HI 2 "register_operand" "r,r"))))] | |
269 | "TARGET_MUL16 || TARGET_MAC16" | |
270 | "@ | |
13fb3a61 BW |
271 | mul16u\t%0, %1, %2 |
272 | umul.aa.ll\t%1, %2" | |
03984308 BW |
273 | [(set_attr "type" "mul16,mac16") |
274 | (set_attr "mode" "SI") | |
275 | (set_attr "length" "3,3")]) | |
276 | ||
277 | (define_insn "muladdhisi" | |
278 | [(set (match_operand:SI 0 "register_operand" "=A") | |
279 | (plus:SI (mult:SI (sign_extend:SI | |
280 | (match_operand:HI 1 "register_operand" "%r")) | |
281 | (sign_extend:SI | |
282 | (match_operand:HI 2 "register_operand" "r"))) | |
283 | (match_operand:SI 3 "register_operand" "0")))] | |
284 | "TARGET_MAC16" | |
13fb3a61 | 285 | "mula.aa.ll\t%1, %2" |
03984308 BW |
286 | [(set_attr "type" "mac16") |
287 | (set_attr "mode" "SI") | |
288 | (set_attr "length" "3")]) | |
289 | ||
290 | (define_insn "mulsubhisi" | |
291 | [(set (match_operand:SI 0 "register_operand" "=A") | |
292 | (minus:SI (match_operand:SI 1 "register_operand" "0") | |
293 | (mult:SI (sign_extend:SI | |
294 | (match_operand:HI 2 "register_operand" "%r")) | |
295 | (sign_extend:SI | |
296 | (match_operand:HI 3 "register_operand" "r")))))] | |
297 | "TARGET_MAC16" | |
13fb3a61 | 298 | "muls.aa.ll\t%2, %3" |
03984308 BW |
299 | [(set_attr "type" "mac16") |
300 | (set_attr "mode" "SI") | |
301 | (set_attr "length" "3")]) | |
302 | ||
303 | (define_insn "mulsf3" | |
304 | [(set (match_operand:SF 0 "register_operand" "=f") | |
305 | (mult:SF (match_operand:SF 1 "register_operand" "%f") | |
306 | (match_operand:SF 2 "register_operand" "f")))] | |
307 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 308 | "mul.s\t%0, %1, %2" |
03984308 BW |
309 | [(set_attr "type" "fmadd") |
310 | (set_attr "mode" "SF") | |
311 | (set_attr "length" "3")]) | |
312 | ||
313 | (define_insn "muladdsf3" | |
314 | [(set (match_operand:SF 0 "register_operand" "=f") | |
315 | (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "%f") | |
316 | (match_operand:SF 2 "register_operand" "f")) | |
317 | (match_operand:SF 3 "register_operand" "0")))] | |
66beb87a | 318 | "TARGET_HARD_FLOAT && TARGET_FUSED_MADD" |
13fb3a61 | 319 | "madd.s\t%0, %1, %2" |
03984308 BW |
320 | [(set_attr "type" "fmadd") |
321 | (set_attr "mode" "SF") | |
322 | (set_attr "length" "3")]) | |
323 | ||
324 | (define_insn "mulsubsf3" | |
325 | [(set (match_operand:SF 0 "register_operand" "=f") | |
326 | (minus:SF (match_operand:SF 1 "register_operand" "0") | |
327 | (mult:SF (match_operand:SF 2 "register_operand" "%f") | |
328 | (match_operand:SF 3 "register_operand" "f"))))] | |
66beb87a | 329 | "TARGET_HARD_FLOAT && TARGET_FUSED_MADD" |
13fb3a61 | 330 | "msub.s\t%0, %2, %3" |
03984308 BW |
331 | [(set_attr "type" "fmadd") |
332 | (set_attr "mode" "SF") | |
333 | (set_attr "length" "3")]) | |
334 | ||
13fb3a61 BW |
335 | \f |
336 | ;; Division. | |
03984308 BW |
337 | |
338 | (define_insn "divsi3" | |
339 | [(set (match_operand:SI 0 "register_operand" "=a") | |
340 | (div:SI (match_operand:SI 1 "register_operand" "r") | |
341 | (match_operand:SI 2 "register_operand" "r")))] | |
342 | "TARGET_DIV32" | |
13fb3a61 | 343 | "quos\t%0, %1, %2" |
03984308 BW |
344 | [(set_attr "type" "div32") |
345 | (set_attr "mode" "SI") | |
346 | (set_attr "length" "3")]) | |
347 | ||
348 | (define_insn "udivsi3" | |
349 | [(set (match_operand:SI 0 "register_operand" "=a") | |
350 | (udiv:SI (match_operand:SI 1 "register_operand" "r") | |
351 | (match_operand:SI 2 "register_operand" "r")))] | |
352 | "TARGET_DIV32" | |
13fb3a61 | 353 | "quou\t%0, %1, %2" |
03984308 BW |
354 | [(set_attr "type" "div32") |
355 | (set_attr "mode" "SI") | |
356 | (set_attr "length" "3")]) | |
357 | ||
358 | (define_insn "divsf3" | |
359 | [(set (match_operand:SF 0 "register_operand" "=f") | |
360 | (div:SF (match_operand:SF 1 "register_operand" "f") | |
361 | (match_operand:SF 2 "register_operand" "f")))] | |
362 | "TARGET_HARD_FLOAT_DIV" | |
13fb3a61 | 363 | "div.s\t%0, %1, %2" |
03984308 BW |
364 | [(set_attr "type" "fdiv") |
365 | (set_attr "mode" "SF") | |
366 | (set_attr "length" "3")]) | |
367 | ||
3219c65b | 368 | (define_insn "*recipsf2" |
03984308 BW |
369 | [(set (match_operand:SF 0 "register_operand" "=f") |
370 | (div:SF (match_operand:SF 1 "const_float_1_operand" "") | |
371 | (match_operand:SF 2 "register_operand" "f")))] | |
372 | "TARGET_HARD_FLOAT_RECIP && flag_unsafe_math_optimizations" | |
13fb3a61 | 373 | "recip.s\t%0, %2" |
03984308 BW |
374 | [(set_attr "type" "fdiv") |
375 | (set_attr "mode" "SF") | |
376 | (set_attr "length" "3")]) | |
377 | ||
13fb3a61 BW |
378 | \f |
379 | ;; Remainders. | |
03984308 BW |
380 | |
381 | (define_insn "modsi3" | |
382 | [(set (match_operand:SI 0 "register_operand" "=a") | |
383 | (mod:SI (match_operand:SI 1 "register_operand" "r") | |
384 | (match_operand:SI 2 "register_operand" "r")))] | |
385 | "TARGET_DIV32" | |
13fb3a61 | 386 | "rems\t%0, %1, %2" |
03984308 BW |
387 | [(set_attr "type" "div32") |
388 | (set_attr "mode" "SI") | |
389 | (set_attr "length" "3")]) | |
390 | ||
391 | (define_insn "umodsi3" | |
392 | [(set (match_operand:SI 0 "register_operand" "=a") | |
393 | (umod:SI (match_operand:SI 1 "register_operand" "r") | |
394 | (match_operand:SI 2 "register_operand" "r")))] | |
395 | "TARGET_DIV32" | |
13fb3a61 | 396 | "remu\t%0, %1, %2" |
03984308 BW |
397 | [(set_attr "type" "div32") |
398 | (set_attr "mode" "SI") | |
399 | (set_attr "length" "3")]) | |
400 | ||
13fb3a61 BW |
401 | \f |
402 | ;; Square roots. | |
03984308 BW |
403 | |
404 | (define_insn "sqrtsf2" | |
405 | [(set (match_operand:SF 0 "register_operand" "=f") | |
406 | (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] | |
407 | "TARGET_HARD_FLOAT_SQRT" | |
13fb3a61 | 408 | "sqrt.s\t%0, %1" |
03984308 BW |
409 | [(set_attr "type" "fsqrt") |
410 | (set_attr "mode" "SF") | |
411 | (set_attr "length" "3")]) | |
412 | ||
3219c65b | 413 | (define_insn "*rsqrtsf2" |
03984308 BW |
414 | [(set (match_operand:SF 0 "register_operand" "=f") |
415 | (div:SF (match_operand:SF 1 "const_float_1_operand" "") | |
416 | (sqrt:SF (match_operand:SF 2 "register_operand" "f"))))] | |
417 | "TARGET_HARD_FLOAT_RSQRT && flag_unsafe_math_optimizations" | |
13fb3a61 | 418 | "rsqrt.s\t%0, %2" |
03984308 BW |
419 | [(set_attr "type" "fsqrt") |
420 | (set_attr "mode" "SF") | |
421 | (set_attr "length" "3")]) | |
422 | ||
13fb3a61 BW |
423 | \f |
424 | ;; Absolute value. | |
03984308 BW |
425 | |
426 | (define_insn "abssi2" | |
427 | [(set (match_operand:SI 0 "register_operand" "=a") | |
428 | (abs:SI (match_operand:SI 1 "register_operand" "r")))] | |
6c2e8d1c | 429 | "TARGET_ABS" |
13fb3a61 | 430 | "abs\t%0, %1" |
03984308 BW |
431 | [(set_attr "type" "arith") |
432 | (set_attr "mode" "SI") | |
433 | (set_attr "length" "3")]) | |
434 | ||
435 | (define_insn "abssf2" | |
436 | [(set (match_operand:SF 0 "register_operand" "=f") | |
437 | (abs:SF (match_operand:SF 1 "register_operand" "f")))] | |
438 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 439 | "abs.s\t%0, %1" |
03984308 BW |
440 | [(set_attr "type" "farith") |
441 | (set_attr "mode" "SF") | |
442 | (set_attr "length" "3")]) | |
443 | ||
13fb3a61 BW |
444 | \f |
445 | ;; Min and max. | |
03984308 | 446 | |
036a2b7a | 447 | (define_insn "<code>si3" |
03984308 | 448 | [(set (match_operand:SI 0 "register_operand" "=a") |
036a2b7a BW |
449 | (any_minmax:SI (match_operand:SI 1 "register_operand" "%r") |
450 | (match_operand:SI 2 "register_operand" "r")))] | |
03984308 | 451 | "TARGET_MINMAX" |
036a2b7a | 452 | "<minmax>\t%0, %1, %2" |
03984308 BW |
453 | [(set_attr "type" "arith") |
454 | (set_attr "mode" "SI") | |
455 | (set_attr "length" "3")]) | |
456 | ||
13fb3a61 | 457 | \f |
09fa8841 BW |
458 | ;; Count leading/trailing zeros and find first bit. |
459 | ||
460 | (define_insn "clzsi2" | |
461 | [(set (match_operand:SI 0 "register_operand" "=a") | |
462 | (clz:SI (match_operand:SI 1 "register_operand" "r")))] | |
463 | "TARGET_NSA" | |
464 | "nsau\t%0, %1" | |
465 | [(set_attr "type" "arith") | |
466 | (set_attr "mode" "SI") | |
467 | (set_attr "length" "3")]) | |
468 | ||
469 | (define_expand "ctzsi2" | |
470 | [(set (match_operand:SI 0 "register_operand" "") | |
471 | (ctz:SI (match_operand:SI 1 "register_operand" "")))] | |
472 | "TARGET_NSA" | |
473 | { | |
474 | rtx temp = gen_reg_rtx (SImode); | |
475 | emit_insn (gen_negsi2 (temp, operands[1])); | |
476 | emit_insn (gen_andsi3 (temp, temp, operands[1])); | |
477 | emit_insn (gen_clzsi2 (temp, temp)); | |
478 | emit_insn (gen_negsi2 (temp, temp)); | |
479 | emit_insn (gen_addsi3 (operands[0], temp, GEN_INT (31))); | |
480 | DONE; | |
481 | }) | |
03984308 BW |
482 | |
483 | (define_expand "ffssi2" | |
484 | [(set (match_operand:SI 0 "register_operand" "") | |
485 | (ffs:SI (match_operand:SI 1 "register_operand" "")))] | |
486 | "TARGET_NSA" | |
03984308 BW |
487 | { |
488 | rtx temp = gen_reg_rtx (SImode); | |
489 | emit_insn (gen_negsi2 (temp, operands[1])); | |
490 | emit_insn (gen_andsi3 (temp, temp, operands[1])); | |
09fa8841 | 491 | emit_insn (gen_clzsi2 (temp, temp)); |
03984308 BW |
492 | emit_insn (gen_negsi2 (temp, temp)); |
493 | emit_insn (gen_addsi3 (operands[0], temp, GEN_INT (32))); | |
494 | DONE; | |
13fb3a61 | 495 | }) |
03984308 | 496 | |
13fb3a61 BW |
497 | \f |
498 | ;; Negation and one's complement. | |
03984308 BW |
499 | |
500 | (define_insn "negsi2" | |
501 | [(set (match_operand:SI 0 "register_operand" "=a") | |
502 | (neg:SI (match_operand:SI 1 "register_operand" "r")))] | |
503 | "" | |
13fb3a61 | 504 | "neg\t%0, %1" |
03984308 BW |
505 | [(set_attr "type" "arith") |
506 | (set_attr "mode" "SI") | |
507 | (set_attr "length" "3")]) | |
508 | ||
509 | (define_expand "one_cmplsi2" | |
510 | [(set (match_operand:SI 0 "register_operand" "") | |
511 | (not:SI (match_operand:SI 1 "register_operand" "")))] | |
512 | "" | |
03984308 BW |
513 | { |
514 | rtx temp = gen_reg_rtx (SImode); | |
515 | emit_insn (gen_movsi (temp, constm1_rtx)); | |
516 | emit_insn (gen_xorsi3 (operands[0], temp, operands[1])); | |
517 | DONE; | |
13fb3a61 | 518 | }) |
03984308 BW |
519 | |
520 | (define_insn "negsf2" | |
521 | [(set (match_operand:SF 0 "register_operand" "=f") | |
522 | (neg:SF (match_operand:SF 1 "register_operand" "f")))] | |
523 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 524 | "neg.s\t%0, %1" |
03984308 BW |
525 | [(set_attr "type" "farith") |
526 | (set_attr "mode" "SF") | |
527 | (set_attr "length" "3")]) | |
528 | ||
13fb3a61 BW |
529 | \f |
530 | ;; Logical instructions. | |
03984308 BW |
531 | |
532 | (define_insn "andsi3" | |
533 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
534 | (and:SI (match_operand:SI 1 "register_operand" "%r,r") | |
535 | (match_operand:SI 2 "mask_operand" "P,r")))] | |
536 | "" | |
537 | "@ | |
13fb3a61 BW |
538 | extui\t%0, %1, 0, %K2 |
539 | and\t%0, %1, %2" | |
03984308 BW |
540 | [(set_attr "type" "arith,arith") |
541 | (set_attr "mode" "SI") | |
542 | (set_attr "length" "3,3")]) | |
543 | ||
544 | (define_insn "iorsi3" | |
545 | [(set (match_operand:SI 0 "register_operand" "=a") | |
546 | (ior:SI (match_operand:SI 1 "register_operand" "%r") | |
547 | (match_operand:SI 2 "register_operand" "r")))] | |
548 | "" | |
13fb3a61 | 549 | "or\t%0, %1, %2" |
03984308 BW |
550 | [(set_attr "type" "arith") |
551 | (set_attr "mode" "SI") | |
552 | (set_attr "length" "3")]) | |
553 | ||
554 | (define_insn "xorsi3" | |
555 | [(set (match_operand:SI 0 "register_operand" "=a") | |
556 | (xor:SI (match_operand:SI 1 "register_operand" "%r") | |
557 | (match_operand:SI 2 "register_operand" "r")))] | |
558 | "" | |
13fb3a61 | 559 | "xor\t%0, %1, %2" |
03984308 BW |
560 | [(set_attr "type" "arith") |
561 | (set_attr "mode" "SI") | |
562 | (set_attr "length" "3")]) | |
563 | ||
13fb3a61 BW |
564 | \f |
565 | ;; Zero-extend instructions. | |
03984308 BW |
566 | |
567 | (define_insn "zero_extendhisi2" | |
568 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
569 | (zero_extend:SI (match_operand:HI 1 "nonimmed_operand" "r,U")))] | |
570 | "" | |
571 | "@ | |
13fb3a61 BW |
572 | extui\t%0, %1, 0, 16 |
573 | l16ui\t%0, %1" | |
03984308 BW |
574 | [(set_attr "type" "arith,load") |
575 | (set_attr "mode" "SI") | |
576 | (set_attr "length" "3,3")]) | |
577 | ||
578 | (define_insn "zero_extendqisi2" | |
579 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
580 | (zero_extend:SI (match_operand:QI 1 "nonimmed_operand" "r,U")))] | |
581 | "" | |
582 | "@ | |
13fb3a61 BW |
583 | extui\t%0, %1, 0, 8 |
584 | l8ui\t%0, %1" | |
03984308 BW |
585 | [(set_attr "type" "arith,load") |
586 | (set_attr "mode" "SI") | |
587 | (set_attr "length" "3,3")]) | |
588 | ||
13fb3a61 BW |
589 | \f |
590 | ;; Sign-extend instructions. | |
03984308 BW |
591 | |
592 | (define_expand "extendhisi2" | |
593 | [(set (match_operand:SI 0 "register_operand" "") | |
594 | (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] | |
595 | "" | |
03984308 BW |
596 | { |
597 | if (sext_operand (operands[1], HImode)) | |
598 | emit_insn (gen_extendhisi2_internal (operands[0], operands[1])); | |
599 | else | |
600 | xtensa_extend_reg (operands[0], operands[1]); | |
601 | DONE; | |
13fb3a61 | 602 | }) |
03984308 BW |
603 | |
604 | (define_insn "extendhisi2_internal" | |
605 | [(set (match_operand:SI 0 "register_operand" "=B,a") | |
606 | (sign_extend:SI (match_operand:HI 1 "sext_operand" "r,U")))] | |
607 | "" | |
608 | "@ | |
13fb3a61 BW |
609 | sext\t%0, %1, 15 |
610 | l16si\t%0, %1" | |
03984308 BW |
611 | [(set_attr "type" "arith,load") |
612 | (set_attr "mode" "SI") | |
613 | (set_attr "length" "3,3")]) | |
614 | ||
615 | (define_expand "extendqisi2" | |
616 | [(set (match_operand:SI 0 "register_operand" "") | |
617 | (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] | |
618 | "" | |
03984308 BW |
619 | { |
620 | if (TARGET_SEXT) | |
13fb3a61 BW |
621 | emit_insn (gen_extendqisi2_internal (operands[0], operands[1])); |
622 | else | |
623 | xtensa_extend_reg (operands[0], operands[1]); | |
03984308 | 624 | DONE; |
13fb3a61 | 625 | }) |
03984308 BW |
626 | |
627 | (define_insn "extendqisi2_internal" | |
628 | [(set (match_operand:SI 0 "register_operand" "=B") | |
629 | (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] | |
630 | "TARGET_SEXT" | |
13fb3a61 | 631 | "sext\t%0, %1, 7" |
03984308 BW |
632 | [(set_attr "type" "arith") |
633 | (set_attr "mode" "SI") | |
634 | (set_attr "length" "3")]) | |
635 | ||
13fb3a61 BW |
636 | \f |
637 | ;; Field extract instructions. | |
03984308 BW |
638 | |
639 | (define_expand "extv" | |
640 | [(set (match_operand:SI 0 "register_operand" "") | |
641 | (sign_extract:SI (match_operand:SI 1 "register_operand" "") | |
642 | (match_operand:SI 2 "const_int_operand" "") | |
643 | (match_operand:SI 3 "const_int_operand" "")))] | |
644 | "TARGET_SEXT" | |
03984308 | 645 | { |
13fb3a61 BW |
646 | if (!sext_fldsz_operand (operands[2], SImode)) |
647 | FAIL; | |
648 | ||
649 | /* We could expand to a right shift followed by SEXT but that's | |
650 | no better than the standard left and right shift sequence. */ | |
651 | if (!lsbitnum_operand (operands[3], SImode)) | |
652 | FAIL; | |
653 | ||
03984308 BW |
654 | emit_insn (gen_extv_internal (operands[0], operands[1], |
655 | operands[2], operands[3])); | |
656 | DONE; | |
13fb3a61 | 657 | }) |
03984308 BW |
658 | |
659 | (define_insn "extv_internal" | |
660 | [(set (match_operand:SI 0 "register_operand" "=a") | |
661 | (sign_extract:SI (match_operand:SI 1 "register_operand" "r") | |
662 | (match_operand:SI 2 "sext_fldsz_operand" "i") | |
663 | (match_operand:SI 3 "lsbitnum_operand" "i")))] | |
664 | "TARGET_SEXT" | |
03984308 BW |
665 | { |
666 | int fldsz = INTVAL (operands[2]); | |
667 | operands[2] = GEN_INT (fldsz - 1); | |
13fb3a61 BW |
668 | return "sext\t%0, %1, %2"; |
669 | } | |
03984308 BW |
670 | [(set_attr "type" "arith") |
671 | (set_attr "mode" "SI") | |
672 | (set_attr "length" "3")]) | |
673 | ||
674 | (define_expand "extzv" | |
675 | [(set (match_operand:SI 0 "register_operand" "") | |
676 | (zero_extract:SI (match_operand:SI 1 "register_operand" "") | |
677 | (match_operand:SI 2 "const_int_operand" "") | |
678 | (match_operand:SI 3 "const_int_operand" "")))] | |
679 | "" | |
03984308 | 680 | { |
13fb3a61 BW |
681 | if (!extui_fldsz_operand (operands[2], SImode)) |
682 | FAIL; | |
03984308 BW |
683 | emit_insn (gen_extzv_internal (operands[0], operands[1], |
684 | operands[2], operands[3])); | |
685 | DONE; | |
13fb3a61 | 686 | }) |
03984308 BW |
687 | |
688 | (define_insn "extzv_internal" | |
689 | [(set (match_operand:SI 0 "register_operand" "=a") | |
690 | (zero_extract:SI (match_operand:SI 1 "register_operand" "r") | |
691 | (match_operand:SI 2 "extui_fldsz_operand" "i") | |
692 | (match_operand:SI 3 "const_int_operand" "i")))] | |
693 | "" | |
03984308 BW |
694 | { |
695 | int shift; | |
696 | if (BITS_BIG_ENDIAN) | |
697 | shift = (32 - (INTVAL (operands[2]) + INTVAL (operands[3]))) & 0x1f; | |
698 | else | |
699 | shift = INTVAL (operands[3]) & 0x1f; | |
700 | operands[3] = GEN_INT (shift); | |
13fb3a61 BW |
701 | return "extui\t%0, %1, %3, %2"; |
702 | } | |
03984308 BW |
703 | [(set_attr "type" "arith") |
704 | (set_attr "mode" "SI") | |
705 | (set_attr "length" "3")]) | |
706 | ||
13fb3a61 BW |
707 | \f |
708 | ;; Conversions. | |
03984308 BW |
709 | |
710 | (define_insn "fix_truncsfsi2" | |
711 | [(set (match_operand:SI 0 "register_operand" "=a") | |
712 | (fix:SI (match_operand:SF 1 "register_operand" "f")))] | |
713 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 714 | "trunc.s\t%0, %1, 0" |
03984308 BW |
715 | [(set_attr "type" "fconv") |
716 | (set_attr "mode" "SF") | |
717 | (set_attr "length" "3")]) | |
718 | ||
719 | (define_insn "fixuns_truncsfsi2" | |
720 | [(set (match_operand:SI 0 "register_operand" "=a") | |
721 | (unsigned_fix:SI (match_operand:SF 1 "register_operand" "f")))] | |
722 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 723 | "utrunc.s\t%0, %1, 0" |
03984308 BW |
724 | [(set_attr "type" "fconv") |
725 | (set_attr "mode" "SF") | |
726 | (set_attr "length" "3")]) | |
727 | ||
728 | (define_insn "floatsisf2" | |
729 | [(set (match_operand:SF 0 "register_operand" "=f") | |
730 | (float:SF (match_operand:SI 1 "register_operand" "a")))] | |
731 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 732 | "float.s\t%0, %1, 0" |
03984308 BW |
733 | [(set_attr "type" "fconv") |
734 | (set_attr "mode" "SF") | |
735 | (set_attr "length" "3")]) | |
736 | ||
737 | (define_insn "floatunssisf2" | |
738 | [(set (match_operand:SF 0 "register_operand" "=f") | |
739 | (unsigned_float:SF (match_operand:SI 1 "register_operand" "a")))] | |
740 | "TARGET_HARD_FLOAT" | |
13fb3a61 | 741 | "ufloat.s\t%0, %1, 0" |
03984308 BW |
742 | [(set_attr "type" "fconv") |
743 | (set_attr "mode" "SF") | |
744 | (set_attr "length" "3")]) | |
745 | ||
13fb3a61 BW |
746 | \f |
747 | ;; Data movement instructions. | |
03984308 BW |
748 | |
749 | ;; 64-bit Integer moves | |
750 | ||
751 | (define_expand "movdi" | |
752 | [(set (match_operand:DI 0 "nonimmed_operand" "") | |
753 | (match_operand:DI 1 "general_operand" ""))] | |
754 | "" | |
03984308 | 755 | { |
633e4eb4 BW |
756 | if (CONSTANT_P (operands[1]) && !TARGET_CONST16) |
757 | operands[1] = force_const_mem (DImode, operands[1]); | |
03984308 | 758 | |
997b8b4d BW |
759 | if (!register_operand (operands[0], DImode) |
760 | && !register_operand (operands[1], DImode)) | |
761 | operands[1] = force_reg (DImode, operands[1]); | |
03984308 | 762 | |
997b8b4d | 763 | operands[1] = xtensa_copy_incoming_a7 (operands[1]); |
13fb3a61 | 764 | }) |
03984308 | 765 | |
633e4eb4 BW |
766 | (define_insn_and_split "movdi_internal" |
767 | [(set (match_operand:DI 0 "nonimmed_operand" "=a,W,a,a,U") | |
768 | (match_operand:DI 1 "move_operand" "r,i,T,U,r"))] | |
03984308 BW |
769 | "register_operand (operands[0], DImode) |
770 | || register_operand (operands[1], DImode)" | |
633e4eb4 BW |
771 | "#" |
772 | "reload_completed" | |
773 | [(set (match_dup 0) (match_dup 2)) | |
774 | (set (match_dup 1) (match_dup 3))] | |
03984308 | 775 | { |
633e4eb4 BW |
776 | xtensa_split_operand_pair (operands, SImode); |
777 | if (reg_overlap_mentioned_p (operands[0], operands[3])) | |
03984308 | 778 | { |
633e4eb4 BW |
779 | rtx tmp; |
780 | tmp = operands[0], operands[0] = operands[1], operands[1] = tmp; | |
781 | tmp = operands[2], operands[2] = operands[3], operands[3] = tmp; | |
03984308 | 782 | } |
633e4eb4 | 783 | }) |
03984308 | 784 | |
03984308 BW |
785 | ;; 32-bit Integer moves |
786 | ||
787 | (define_expand "movsi" | |
788 | [(set (match_operand:SI 0 "nonimmed_operand" "") | |
789 | (match_operand:SI 1 "general_operand" ""))] | |
790 | "" | |
03984308 BW |
791 | { |
792 | if (xtensa_emit_move_sequence (operands, SImode)) | |
793 | DONE; | |
13fb3a61 | 794 | }) |
03984308 BW |
795 | |
796 | (define_insn "movsi_internal" | |
f42f5a1b BW |
797 | [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,D,R,R,a,q,a,W,a,a,U,*a,*A") |
798 | (match_operand:SI 1 "move_operand" "M,D,d,R,D,d,r,r,I,i,T,U,r,*A,*r"))] | |
a8cacfd2 | 799 | "xtensa_valid_move (SImode, operands)" |
03984308 | 800 | "@ |
13fb3a61 BW |
801 | movi.n\t%0, %x1 |
802 | mov.n\t%0, %1 | |
803 | mov.n\t%0, %1 | |
804 | %v1l32i.n\t%0, %1 | |
805 | %v0s32i.n\t%1, %0 | |
806 | %v0s32i.n\t%1, %0 | |
807 | mov\t%0, %1 | |
808 | movsp\t%0, %1 | |
809 | movi\t%0, %x1 | |
810 | const16\t%0, %t1\;const16\t%0, %b1 | |
811 | %v1l32r\t%0, %1 | |
812 | %v1l32i\t%0, %1 | |
813 | %v0s32i\t%1, %0 | |
12a8ee33 BW |
814 | rsr\t%0, ACCLO |
815 | wsr\t%1, ACCLO" | |
f42f5a1b | 816 | [(set_attr "type" "move,move,move,load,store,store,move,move,move,move,load,load,store,rsr,wsr") |
03984308 | 817 | (set_attr "mode" "SI") |
f42f5a1b | 818 | (set_attr "length" "2,2,2,2,2,2,3,3,3,6,3,3,3,3,3")]) |
03984308 BW |
819 | |
820 | ;; 16-bit Integer moves | |
821 | ||
822 | (define_expand "movhi" | |
823 | [(set (match_operand:HI 0 "nonimmed_operand" "") | |
824 | (match_operand:HI 1 "general_operand" ""))] | |
825 | "" | |
03984308 BW |
826 | { |
827 | if (xtensa_emit_move_sequence (operands, HImode)) | |
828 | DONE; | |
13fb3a61 | 829 | }) |
03984308 BW |
830 | |
831 | (define_insn "movhi_internal" | |
832 | [(set (match_operand:HI 0 "nonimmed_operand" "=D,D,a,a,a,U,*a,*A") | |
833 | (match_operand:HI 1 "move_operand" "M,d,r,I,U,r,*A,*r"))] | |
a8cacfd2 | 834 | "xtensa_valid_move (HImode, operands)" |
03984308 | 835 | "@ |
13fb3a61 BW |
836 | movi.n\t%0, %x1 |
837 | mov.n\t%0, %1 | |
838 | mov\t%0, %1 | |
839 | movi\t%0, %x1 | |
840 | %v1l16ui\t%0, %1 | |
841 | %v0s16i\t%1, %0 | |
12a8ee33 BW |
842 | rsr\t%0, ACCLO |
843 | wsr\t%1, ACCLO" | |
03984308 BW |
844 | [(set_attr "type" "move,move,move,move,load,store,rsr,wsr") |
845 | (set_attr "mode" "HI") | |
846 | (set_attr "length" "2,2,3,3,3,3,3,3")]) | |
847 | ||
848 | ;; 8-bit Integer moves | |
849 | ||
850 | (define_expand "movqi" | |
851 | [(set (match_operand:QI 0 "nonimmed_operand" "") | |
852 | (match_operand:QI 1 "general_operand" ""))] | |
853 | "" | |
03984308 BW |
854 | { |
855 | if (xtensa_emit_move_sequence (operands, QImode)) | |
856 | DONE; | |
13fb3a61 | 857 | }) |
03984308 BW |
858 | |
859 | (define_insn "movqi_internal" | |
860 | [(set (match_operand:QI 0 "nonimmed_operand" "=D,D,a,a,a,U,*a,*A") | |
861 | (match_operand:QI 1 "move_operand" "M,d,r,I,U,r,*A,*r"))] | |
a8cacfd2 | 862 | "xtensa_valid_move (QImode, operands)" |
03984308 | 863 | "@ |
13fb3a61 BW |
864 | movi.n\t%0, %x1 |
865 | mov.n\t%0, %1 | |
866 | mov\t%0, %1 | |
867 | movi\t%0, %x1 | |
868 | %v1l8ui\t%0, %1 | |
869 | %v0s8i\t%1, %0 | |
12a8ee33 BW |
870 | rsr\t%0, ACCLO |
871 | wsr\t%1, ACCLO" | |
03984308 BW |
872 | [(set_attr "type" "move,move,move,move,load,store,rsr,wsr") |
873 | (set_attr "mode" "QI") | |
874 | (set_attr "length" "2,2,3,3,3,3,3,3")]) | |
875 | ||
876 | ;; 32-bit floating point moves | |
877 | ||
878 | (define_expand "movsf" | |
879 | [(set (match_operand:SF 0 "nonimmed_operand" "") | |
880 | (match_operand:SF 1 "general_operand" ""))] | |
881 | "" | |
03984308 | 882 | { |
f42f5a1b | 883 | if (!TARGET_CONST16 && CONSTANT_P (operands[1])) |
03984308 BW |
884 | operands[1] = force_const_mem (SFmode, operands[1]); |
885 | ||
997b8b4d BW |
886 | if ((!register_operand (operands[0], SFmode) |
887 | && !register_operand (operands[1], SFmode)) | |
888 | || (FP_REG_P (xt_true_regnum (operands[0])) | |
889 | && !(reload_in_progress | reload_completed) | |
890 | && (constantpool_mem_p (operands[1]) | |
891 | || CONSTANT_P (operands[1])))) | |
892 | operands[1] = force_reg (SFmode, operands[1]); | |
893 | ||
894 | operands[1] = xtensa_copy_incoming_a7 (operands[1]); | |
13fb3a61 | 895 | }) |
03984308 BW |
896 | |
897 | (define_insn "movsf_internal" | |
f42f5a1b | 898 | [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,U,D,D,R,a,f,a,W,a,a,U") |
633e4eb4 | 899 | (match_operand:SF 1 "move_operand" "f,U,f,d,R,d,r,r,f,iF,T,U,r"))] |
03984308 BW |
900 | "((register_operand (operands[0], SFmode) |
901 | || register_operand (operands[1], SFmode)) | |
f42f5a1b BW |
902 | && !(FP_REG_P (xt_true_regnum (operands[0])) |
903 | && (constantpool_mem_p (operands[1]) || CONSTANT_P (operands[1]))))" | |
03984308 | 904 | "@ |
13fb3a61 BW |
905 | mov.s\t%0, %1 |
906 | %v1lsi\t%0, %1 | |
907 | %v0ssi\t%1, %0 | |
908 | mov.n\t%0, %1 | |
909 | %v1l32i.n\t%0, %1 | |
910 | %v0s32i.n\t%1, %0 | |
911 | mov\t%0, %1 | |
912 | wfr\t%0, %1 | |
913 | rfr\t%0, %1 | |
914 | const16\t%0, %t1\;const16\t%0, %b1 | |
915 | %v1l32r\t%0, %1 | |
916 | %v1l32i\t%0, %1 | |
917 | %v0s32i\t%1, %0" | |
f42f5a1b | 918 | [(set_attr "type" "farith,fload,fstore,move,load,store,move,farith,farith,move,load,load,store") |
03984308 | 919 | (set_attr "mode" "SF") |
f42f5a1b | 920 | (set_attr "length" "3,3,3,2,2,2,3,3,3,6,3,3,3")]) |
03984308 | 921 | |
3219c65b BW |
922 | (define_insn "*lsiu" |
923 | [(set (match_operand:SF 0 "register_operand" "=f") | |
924 | (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "+a") | |
925 | (match_operand:SI 2 "fpmem_offset_operand" "i")))) | |
926 | (set (match_dup 1) | |
927 | (plus:SI (match_dup 1) (match_dup 2)))] | |
03984308 | 928 | "TARGET_HARD_FLOAT" |
03984308 | 929 | { |
7a29f483 | 930 | if (volatile_refs_p (PATTERN (insn))) |
13fb3a61 BW |
931 | output_asm_insn ("memw", operands); |
932 | return "lsiu\t%0, %1, %2"; | |
933 | } | |
03984308 BW |
934 | [(set_attr "type" "fload") |
935 | (set_attr "mode" "SF") | |
936 | (set_attr "length" "3")]) | |
937 | ||
3219c65b BW |
938 | (define_insn "*ssiu" |
939 | [(set (mem:SF (plus:SI (match_operand:SI 0 "register_operand" "+a") | |
940 | (match_operand:SI 1 "fpmem_offset_operand" "i"))) | |
941 | (match_operand:SF 2 "register_operand" "f")) | |
942 | (set (match_dup 0) | |
943 | (plus:SI (match_dup 0) (match_dup 1)))] | |
03984308 | 944 | "TARGET_HARD_FLOAT" |
03984308 | 945 | { |
7a29f483 | 946 | if (volatile_refs_p (PATTERN (insn))) |
13fb3a61 BW |
947 | output_asm_insn ("memw", operands); |
948 | return "ssiu\t%2, %0, %1"; | |
949 | } | |
03984308 BW |
950 | [(set_attr "type" "fstore") |
951 | (set_attr "mode" "SF") | |
952 | (set_attr "length" "3")]) | |
953 | ||
954 | ;; 64-bit floating point moves | |
955 | ||
956 | (define_expand "movdf" | |
957 | [(set (match_operand:DF 0 "nonimmed_operand" "") | |
958 | (match_operand:DF 1 "general_operand" ""))] | |
959 | "" | |
03984308 | 960 | { |
633e4eb4 BW |
961 | if (CONSTANT_P (operands[1]) && !TARGET_CONST16) |
962 | operands[1] = force_const_mem (DFmode, operands[1]); | |
03984308 | 963 | |
997b8b4d BW |
964 | if (!register_operand (operands[0], DFmode) |
965 | && !register_operand (operands[1], DFmode)) | |
966 | operands[1] = force_reg (DFmode, operands[1]); | |
03984308 | 967 | |
997b8b4d | 968 | operands[1] = xtensa_copy_incoming_a7 (operands[1]); |
13fb3a61 | 969 | }) |
03984308 | 970 | |
633e4eb4 BW |
971 | (define_insn_and_split "movdf_internal" |
972 | [(set (match_operand:DF 0 "nonimmed_operand" "=a,W,a,a,U") | |
973 | (match_operand:DF 1 "move_operand" "r,iF,T,U,r"))] | |
03984308 BW |
974 | "register_operand (operands[0], DFmode) |
975 | || register_operand (operands[1], DFmode)" | |
633e4eb4 BW |
976 | "#" |
977 | "reload_completed" | |
978 | [(set (match_dup 0) (match_dup 2)) | |
979 | (set (match_dup 1) (match_dup 3))] | |
03984308 | 980 | { |
633e4eb4 BW |
981 | xtensa_split_operand_pair (operands, SFmode); |
982 | if (reg_overlap_mentioned_p (operands[0], operands[3])) | |
03984308 | 983 | { |
633e4eb4 BW |
984 | rtx tmp; |
985 | tmp = operands[0], operands[0] = operands[1], operands[1] = tmp; | |
986 | tmp = operands[2], operands[2] = operands[3], operands[3] = tmp; | |
03984308 | 987 | } |
633e4eb4 | 988 | }) |
03984308 BW |
989 | |
990 | ;; Block moves | |
991 | ||
70128ad9 | 992 | (define_expand "movmemsi" |
03984308 BW |
993 | [(parallel [(set (match_operand:BLK 0 "" "") |
994 | (match_operand:BLK 1 "" "")) | |
995 | (use (match_operand:SI 2 "arith_operand" "")) | |
996 | (use (match_operand:SI 3 "const_int_operand" ""))])] | |
997 | "" | |
03984308 | 998 | { |
13fb3a61 BW |
999 | if (!xtensa_expand_block_move (operands)) |
1000 | FAIL; | |
03984308 | 1001 | DONE; |
13fb3a61 | 1002 | }) |
03984308 | 1003 | |
13fb3a61 BW |
1004 | \f |
1005 | ;; Shift instructions. | |
03984308 | 1006 | |
997b8b4d BW |
1007 | (define_expand "ashlsi3" |
1008 | [(set (match_operand:SI 0 "register_operand" "") | |
1009 | (ashift:SI (match_operand:SI 1 "register_operand" "") | |
1010 | (match_operand:SI 2 "arith_operand" "")))] | |
1011 | "" | |
1012 | { | |
1013 | operands[1] = xtensa_copy_incoming_a7 (operands[1]); | |
1014 | }) | |
1015 | ||
1016 | (define_insn "ashlsi3_internal" | |
03984308 BW |
1017 | [(set (match_operand:SI 0 "register_operand" "=a,a") |
1018 | (ashift:SI (match_operand:SI 1 "register_operand" "r,r") | |
1019 | (match_operand:SI 2 "arith_operand" "J,r")))] | |
1020 | "" | |
1021 | "@ | |
13fb3a61 BW |
1022 | slli\t%0, %1, %R2 |
1023 | ssl\t%2\;sll\t%0, %1" | |
03984308 BW |
1024 | [(set_attr "type" "arith,arith") |
1025 | (set_attr "mode" "SI") | |
1026 | (set_attr "length" "3,6")]) | |
1027 | ||
1028 | (define_insn "ashrsi3" | |
1029 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
1030 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r") | |
1031 | (match_operand:SI 2 "arith_operand" "J,r")))] | |
1032 | "" | |
1033 | "@ | |
13fb3a61 BW |
1034 | srai\t%0, %1, %R2 |
1035 | ssr\t%2\;sra\t%0, %1" | |
03984308 BW |
1036 | [(set_attr "type" "arith,arith") |
1037 | (set_attr "mode" "SI") | |
1038 | (set_attr "length" "3,6")]) | |
1039 | ||
1040 | (define_insn "lshrsi3" | |
1041 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
1042 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") | |
1043 | (match_operand:SI 2 "arith_operand" "J,r")))] | |
1044 | "" | |
03984308 BW |
1045 | { |
1046 | if (which_alternative == 0) | |
1047 | { | |
1048 | if ((INTVAL (operands[2]) & 0x1f) < 16) | |
13fb3a61 | 1049 | return "srli\t%0, %1, %R2"; |
03984308 | 1050 | else |
13fb3a61 | 1051 | return "extui\t%0, %1, %R2, %L2"; |
03984308 | 1052 | } |
13fb3a61 BW |
1053 | return "ssr\t%2\;srl\t%0, %1"; |
1054 | } | |
03984308 BW |
1055 | [(set_attr "type" "arith,arith") |
1056 | (set_attr "mode" "SI") | |
1057 | (set_attr "length" "3,6")]) | |
1058 | ||
1059 | (define_insn "rotlsi3" | |
1060 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
1061 | (rotate:SI (match_operand:SI 1 "register_operand" "r,r") | |
1062 | (match_operand:SI 2 "arith_operand" "J,r")))] | |
1063 | "" | |
1064 | "@ | |
13fb3a61 BW |
1065 | ssai\t%L2\;src\t%0, %1, %1 |
1066 | ssl\t%2\;src\t%0, %1, %1" | |
03984308 BW |
1067 | [(set_attr "type" "multi,multi") |
1068 | (set_attr "mode" "SI") | |
1069 | (set_attr "length" "6,6")]) | |
1070 | ||
1071 | (define_insn "rotrsi3" | |
1072 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
1073 | (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") | |
1074 | (match_operand:SI 2 "arith_operand" "J,r")))] | |
1075 | "" | |
1076 | "@ | |
13fb3a61 BW |
1077 | ssai\t%R2\;src\t%0, %1, %1 |
1078 | ssr\t%2\;src\t%0, %1, %1" | |
03984308 BW |
1079 | [(set_attr "type" "multi,multi") |
1080 | (set_attr "mode" "SI") | |
1081 | (set_attr "length" "6,6")]) | |
1082 | ||
13fb3a61 BW |
1083 | \f |
1084 | ;; Comparisons. | |
0c14a54d | 1085 | |
13fb3a61 BW |
1086 | ;; Handle comparisons by stashing away the operands and then using that |
1087 | ;; information in the subsequent conditional branch. | |
03984308 BW |
1088 | |
1089 | (define_expand "cmpsi" | |
1090 | [(set (cc0) | |
1091 | (compare:CC (match_operand:SI 0 "register_operand" "") | |
1092 | (match_operand:SI 1 "nonmemory_operand" "")))] | |
1093 | "" | |
03984308 BW |
1094 | { |
1095 | branch_cmp[0] = operands[0]; | |
1096 | branch_cmp[1] = operands[1]; | |
1097 | branch_type = CMP_SI; | |
1098 | DONE; | |
13fb3a61 | 1099 | }) |
03984308 | 1100 | |
03984308 BW |
1101 | (define_expand "cmpsf" |
1102 | [(set (cc0) | |
1103 | (compare:CC (match_operand:SF 0 "register_operand" "") | |
1104 | (match_operand:SF 1 "register_operand" "")))] | |
1105 | "TARGET_HARD_FLOAT" | |
03984308 BW |
1106 | { |
1107 | branch_cmp[0] = operands[0]; | |
1108 | branch_cmp[1] = operands[1]; | |
1109 | branch_type = CMP_SF; | |
1110 | DONE; | |
13fb3a61 | 1111 | }) |
03984308 | 1112 | |
13fb3a61 BW |
1113 | \f |
1114 | ;; Conditional branches. | |
03984308 | 1115 | |
036a2b7a | 1116 | (define_expand "b<code>" |
03984308 | 1117 | [(set (pc) |
036a2b7a | 1118 | (if_then_else (any_cond (cc0) (const_int 0)) |
03984308 BW |
1119 | (label_ref (match_operand 0 "" "")) |
1120 | (pc)))] | |
1121 | "" | |
03984308 | 1122 | { |
036a2b7a | 1123 | xtensa_expand_conditional_branch (operands, <CODE>); |
03984308 | 1124 | DONE; |
13fb3a61 | 1125 | }) |
03984308 BW |
1126 | |
1127 | ;; Branch patterns for standard integer comparisons | |
1128 | ||
3219c65b | 1129 | (define_insn "*btrue" |
03984308 BW |
1130 | [(set (pc) |
1131 | (if_then_else (match_operator 3 "branch_operator" | |
036a2b7a BW |
1132 | [(match_operand:SI 0 "register_operand" "r,r") |
1133 | (match_operand:SI 1 "branch_operand" "K,r")]) | |
03984308 BW |
1134 | (label_ref (match_operand 2 "" "")) |
1135 | (pc)))] | |
1136 | "" | |
03984308 | 1137 | { |
036a2b7a | 1138 | return xtensa_emit_branch (false, which_alternative == 0, operands); |
13fb3a61 | 1139 | } |
03984308 BW |
1140 | [(set_attr "type" "jump,jump") |
1141 | (set_attr "mode" "none") | |
1142 | (set_attr "length" "3,3")]) | |
1143 | ||
3219c65b | 1144 | (define_insn "*bfalse" |
03984308 BW |
1145 | [(set (pc) |
1146 | (if_then_else (match_operator 3 "branch_operator" | |
036a2b7a BW |
1147 | [(match_operand:SI 0 "register_operand" "r,r") |
1148 | (match_operand:SI 1 "branch_operand" "K,r")]) | |
03984308 BW |
1149 | (pc) |
1150 | (label_ref (match_operand 2 "" ""))))] | |
1151 | "" | |
03984308 | 1152 | { |
036a2b7a | 1153 | return xtensa_emit_branch (true, which_alternative == 0, operands); |
13fb3a61 | 1154 | } |
03984308 BW |
1155 | [(set_attr "type" "jump,jump") |
1156 | (set_attr "mode" "none") | |
1157 | (set_attr "length" "3,3")]) | |
1158 | ||
3219c65b | 1159 | (define_insn "*ubtrue" |
03984308 BW |
1160 | [(set (pc) |
1161 | (if_then_else (match_operator 3 "ubranch_operator" | |
036a2b7a BW |
1162 | [(match_operand:SI 0 "register_operand" "r,r") |
1163 | (match_operand:SI 1 "ubranch_operand" "L,r")]) | |
03984308 BW |
1164 | (label_ref (match_operand 2 "" "")) |
1165 | (pc)))] | |
1166 | "" | |
03984308 | 1167 | { |
036a2b7a | 1168 | return xtensa_emit_branch (false, which_alternative == 0, operands); |
13fb3a61 | 1169 | } |
03984308 BW |
1170 | [(set_attr "type" "jump,jump") |
1171 | (set_attr "mode" "none") | |
1172 | (set_attr "length" "3,3")]) | |
1173 | ||
3219c65b | 1174 | (define_insn "*ubfalse" |
03984308 BW |
1175 | [(set (pc) |
1176 | (if_then_else (match_operator 3 "ubranch_operator" | |
1177 | [(match_operand:SI 0 "register_operand" "r,r") | |
1178 | (match_operand:SI 1 "ubranch_operand" "L,r")]) | |
1179 | (pc) | |
1180 | (label_ref (match_operand 2 "" ""))))] | |
1181 | "" | |
03984308 | 1182 | { |
036a2b7a | 1183 | return xtensa_emit_branch (true, which_alternative == 0, operands); |
13fb3a61 | 1184 | } |
03984308 BW |
1185 | [(set_attr "type" "jump,jump") |
1186 | (set_attr "mode" "none") | |
1187 | (set_attr "length" "3,3")]) | |
1188 | ||
1189 | ;; Branch patterns for bit testing | |
1190 | ||
3219c65b | 1191 | (define_insn "*bittrue" |
03984308 BW |
1192 | [(set (pc) |
1193 | (if_then_else (match_operator 3 "boolean_operator" | |
1194 | [(zero_extract:SI | |
1195 | (match_operand:SI 0 "register_operand" "r,r") | |
1196 | (const_int 1) | |
1197 | (match_operand:SI 1 "arith_operand" "J,r")) | |
1198 | (const_int 0)]) | |
1199 | (label_ref (match_operand 2 "" "")) | |
1200 | (pc)))] | |
1201 | "" | |
03984308 | 1202 | { |
036a2b7a | 1203 | return xtensa_emit_bit_branch (false, which_alternative == 0, operands); |
13fb3a61 | 1204 | } |
03984308 BW |
1205 | [(set_attr "type" "jump") |
1206 | (set_attr "mode" "none") | |
1207 | (set_attr "length" "3")]) | |
1208 | ||
3219c65b | 1209 | (define_insn "*bitfalse" |
03984308 BW |
1210 | [(set (pc) |
1211 | (if_then_else (match_operator 3 "boolean_operator" | |
1212 | [(zero_extract:SI | |
1213 | (match_operand:SI 0 "register_operand" "r,r") | |
1214 | (const_int 1) | |
1215 | (match_operand:SI 1 "arith_operand" "J,r")) | |
1216 | (const_int 0)]) | |
1217 | (pc) | |
1218 | (label_ref (match_operand 2 "" ""))))] | |
1219 | "" | |
03984308 | 1220 | { |
036a2b7a | 1221 | return xtensa_emit_bit_branch (true, which_alternative == 0, operands); |
13fb3a61 | 1222 | } |
03984308 BW |
1223 | [(set_attr "type" "jump") |
1224 | (set_attr "mode" "none") | |
1225 | (set_attr "length" "3")]) | |
1226 | ||
3219c65b | 1227 | (define_insn "*masktrue" |
03984308 BW |
1228 | [(set (pc) |
1229 | (if_then_else (match_operator 3 "boolean_operator" | |
1230 | [(and:SI (match_operand:SI 0 "register_operand" "r") | |
1231 | (match_operand:SI 1 "register_operand" "r")) | |
1232 | (const_int 0)]) | |
1233 | (label_ref (match_operand 2 "" "")) | |
1234 | (pc)))] | |
1235 | "" | |
03984308 BW |
1236 | { |
1237 | switch (GET_CODE (operands[3])) | |
1238 | { | |
13fb3a61 BW |
1239 | case EQ: return "bnone\t%0, %1, %2"; |
1240 | case NE: return "bany\t%0, %1, %2"; | |
177b6be0 | 1241 | default: gcc_unreachable (); |
03984308 | 1242 | } |
13fb3a61 | 1243 | } |
03984308 BW |
1244 | [(set_attr "type" "jump") |
1245 | (set_attr "mode" "none") | |
1246 | (set_attr "length" "3")]) | |
1247 | ||
3219c65b | 1248 | (define_insn "*maskfalse" |
03984308 BW |
1249 | [(set (pc) |
1250 | (if_then_else (match_operator 3 "boolean_operator" | |
1251 | [(and:SI (match_operand:SI 0 "register_operand" "r") | |
1252 | (match_operand:SI 1 "register_operand" "r")) | |
1253 | (const_int 0)]) | |
1254 | (pc) | |
1255 | (label_ref (match_operand 2 "" ""))))] | |
1256 | "" | |
03984308 BW |
1257 | { |
1258 | switch (GET_CODE (operands[3])) | |
1259 | { | |
13fb3a61 BW |
1260 | case EQ: return "bany\t%0, %1, %2"; |
1261 | case NE: return "bnone\t%0, %1, %2"; | |
177b6be0 | 1262 | default: gcc_unreachable (); |
03984308 | 1263 | } |
13fb3a61 | 1264 | } |
03984308 BW |
1265 | [(set_attr "type" "jump") |
1266 | (set_attr "mode" "none") | |
1267 | (set_attr "length" "3")]) | |
1268 | ||
1269 | ||
13fb3a61 BW |
1270 | ;; Define the loop insns used by bct optimization to represent the |
1271 | ;; start and end of a zero-overhead loop (in loop.c). This start | |
1272 | ;; template generates the loop insn; the end template doesn't generate | |
1273 | ;; any instructions since loop end is handled in hardware. | |
03984308 BW |
1274 | |
1275 | (define_insn "zero_cost_loop_start" | |
13fb3a61 BW |
1276 | [(set (pc) |
1277 | (if_then_else (eq (match_operand:SI 0 "register_operand" "a") | |
1278 | (const_int 0)) | |
1279 | (label_ref (match_operand 1 "" "")) | |
1280 | (pc))) | |
3219c65b BW |
1281 | (set (reg:SI 19) |
1282 | (plus:SI (match_dup 0) (const_int -1)))] | |
03984308 | 1283 | "" |
13fb3a61 | 1284 | "loopnez\t%0, %l1" |
03984308 BW |
1285 | [(set_attr "type" "jump") |
1286 | (set_attr "mode" "none") | |
1287 | (set_attr "length" "3")]) | |
1288 | ||
1289 | (define_insn "zero_cost_loop_end" | |
13fb3a61 BW |
1290 | [(set (pc) |
1291 | (if_then_else (ne (reg:SI 19) (const_int 0)) | |
1292 | (label_ref (match_operand 0 "" "")) | |
1293 | (pc))) | |
3219c65b BW |
1294 | (set (reg:SI 19) |
1295 | (plus:SI (reg:SI 19) (const_int -1)))] | |
03984308 | 1296 | "" |
13fb3a61 | 1297 | { |
03984308 | 1298 | xtensa_emit_loop_end (insn, operands); |
13fb3a61 BW |
1299 | return ""; |
1300 | } | |
03984308 BW |
1301 | [(set_attr "type" "jump") |
1302 | (set_attr "mode" "none") | |
1303 | (set_attr "length" "0")]) | |
1304 | ||
13fb3a61 BW |
1305 | \f |
1306 | ;; Setting a register from a comparison. | |
03984308 | 1307 | |
036a2b7a | 1308 | (define_expand "s<code>" |
03984308 | 1309 | [(set (match_operand:SI 0 "register_operand" "") |
036a2b7a BW |
1310 | (any_scc:SI (match_dup 1) |
1311 | (match_dup 2)))] | |
03984308 | 1312 | "" |
03984308 | 1313 | { |
036a2b7a | 1314 | operands[1] = gen_rtx_<CODE> (SImode, branch_cmp[0], branch_cmp[1]); |
13fb3a61 BW |
1315 | if (!xtensa_expand_scc (operands)) |
1316 | FAIL; | |
03984308 | 1317 | DONE; |
13fb3a61 | 1318 | }) |
03984308 | 1319 | |
13fb3a61 BW |
1320 | \f |
1321 | ;; Conditional moves. | |
03984308 BW |
1322 | |
1323 | (define_expand "movsicc" | |
1324 | [(set (match_operand:SI 0 "register_operand" "") | |
1325 | (if_then_else:SI (match_operand 1 "comparison_operator" "") | |
1326 | (match_operand:SI 2 "register_operand" "") | |
1327 | (match_operand:SI 3 "register_operand" "")))] | |
1328 | "" | |
03984308 | 1329 | { |
13fb3a61 BW |
1330 | if (!xtensa_expand_conditional_move (operands, 0)) |
1331 | FAIL; | |
03984308 | 1332 | DONE; |
13fb3a61 | 1333 | }) |
03984308 BW |
1334 | |
1335 | (define_expand "movsfcc" | |
1336 | [(set (match_operand:SF 0 "register_operand" "") | |
1337 | (if_then_else:SF (match_operand 1 "comparison_operator" "") | |
1338 | (match_operand:SF 2 "register_operand" "") | |
1339 | (match_operand:SF 3 "register_operand" "")))] | |
1340 | "" | |
03984308 | 1341 | { |
13fb3a61 BW |
1342 | if (!xtensa_expand_conditional_move (operands, 1)) |
1343 | FAIL; | |
03984308 | 1344 | DONE; |
13fb3a61 | 1345 | }) |
03984308 BW |
1346 | |
1347 | (define_insn "movsicc_internal0" | |
1348 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
1349 | (if_then_else:SI (match_operator 4 "branch_operator" | |
1350 | [(match_operand:SI 1 "register_operand" "r,r") | |
1351 | (const_int 0)]) | |
1352 | (match_operand:SI 2 "register_operand" "r,0") | |
1353 | (match_operand:SI 3 "register_operand" "0,r")))] | |
1354 | "" | |
03984308 | 1355 | { |
036a2b7a | 1356 | return xtensa_emit_movcc (which_alternative == 1, false, false, operands); |
13fb3a61 | 1357 | } |
03984308 BW |
1358 | [(set_attr "type" "move,move") |
1359 | (set_attr "mode" "SI") | |
1360 | (set_attr "length" "3,3")]) | |
1361 | ||
1362 | (define_insn "movsicc_internal1" | |
1363 | [(set (match_operand:SI 0 "register_operand" "=a,a") | |
1364 | (if_then_else:SI (match_operator 4 "boolean_operator" | |
1365 | [(match_operand:CC 1 "register_operand" "b,b") | |
1366 | (const_int 0)]) | |
1367 | (match_operand:SI 2 "register_operand" "r,0") | |
1368 | (match_operand:SI 3 "register_operand" "0,r")))] | |
1369 | "TARGET_BOOLEANS" | |
03984308 | 1370 | { |
036a2b7a | 1371 | return xtensa_emit_movcc (which_alternative == 1, false, true, operands); |
13fb3a61 | 1372 | } |
03984308 BW |
1373 | [(set_attr "type" "move,move") |
1374 | (set_attr "mode" "SI") | |
1375 | (set_attr "length" "3,3")]) | |
1376 | ||
1377 | (define_insn "movsfcc_internal0" | |
1378 | [(set (match_operand:SF 0 "register_operand" "=a,a,f,f") | |
1379 | (if_then_else:SF (match_operator 4 "branch_operator" | |
1380 | [(match_operand:SI 1 "register_operand" "r,r,r,r") | |
1381 | (const_int 0)]) | |
1382 | (match_operand:SF 2 "register_operand" "r,0,f,0") | |
1383 | (match_operand:SF 3 "register_operand" "0,r,0,f")))] | |
1384 | "" | |
03984308 | 1385 | { |
036a2b7a BW |
1386 | return xtensa_emit_movcc ((which_alternative & 1) == 1, |
1387 | which_alternative >= 2, false, operands); | |
13fb3a61 | 1388 | } |
03984308 BW |
1389 | [(set_attr "type" "move,move,move,move") |
1390 | (set_attr "mode" "SF") | |
1391 | (set_attr "length" "3,3,3,3")]) | |
1392 | ||
1393 | (define_insn "movsfcc_internal1" | |
1394 | [(set (match_operand:SF 0 "register_operand" "=a,a,f,f") | |
1395 | (if_then_else:SF (match_operator 4 "boolean_operator" | |
1396 | [(match_operand:CC 1 "register_operand" "b,b,b,b") | |
1397 | (const_int 0)]) | |
1398 | (match_operand:SF 2 "register_operand" "r,0,f,0") | |
1399 | (match_operand:SF 3 "register_operand" "0,r,0,f")))] | |
1400 | "TARGET_BOOLEANS" | |
03984308 | 1401 | { |
036a2b7a BW |
1402 | return xtensa_emit_movcc ((which_alternative & 1) == 1, |
1403 | which_alternative >= 2, true, operands); | |
13fb3a61 | 1404 | } |
03984308 BW |
1405 | [(set_attr "type" "move,move,move,move") |
1406 | (set_attr "mode" "SF") | |
1407 | (set_attr "length" "3,3,3,3")]) | |
1408 | ||
13fb3a61 BW |
1409 | \f |
1410 | ;; Floating-point comparisons. | |
03984308 | 1411 | |
036a2b7a | 1412 | (define_insn "s<code>_sf" |
03984308 | 1413 | [(set (match_operand:CC 0 "register_operand" "=b") |
036a2b7a BW |
1414 | (any_scc_sf:CC (match_operand:SF 1 "register_operand" "f") |
1415 | (match_operand:SF 2 "register_operand" "f")))] | |
03984308 | 1416 | "TARGET_HARD_FLOAT" |
036a2b7a | 1417 | "o<code>.s\t%0, %1, %2" |
03984308 BW |
1418 | [(set_attr "type" "farith") |
1419 | (set_attr "mode" "BL") | |
1420 | (set_attr "length" "3")]) | |
1421 | ||
13fb3a61 BW |
1422 | \f |
1423 | ;; Unconditional branches. | |
03984308 BW |
1424 | |
1425 | (define_insn "jump" | |
1426 | [(set (pc) | |
1427 | (label_ref (match_operand 0 "" "")))] | |
1428 | "" | |
13fb3a61 | 1429 | "j\t%l0" |
03984308 BW |
1430 | [(set_attr "type" "jump") |
1431 | (set_attr "mode" "none") | |
1432 | (set_attr "length" "3")]) | |
1433 | ||
1434 | (define_expand "indirect_jump" | |
13fb3a61 BW |
1435 | [(set (pc) |
1436 | (match_operand 0 "register_operand" ""))] | |
03984308 | 1437 | "" |
03984308 BW |
1438 | { |
1439 | rtx dest = operands[0]; | |
1440 | if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) | |
1441 | operands[0] = copy_to_mode_reg (Pmode, dest); | |
1442 | ||
1443 | emit_jump_insn (gen_indirect_jump_internal (dest)); | |
1444 | DONE; | |
13fb3a61 | 1445 | }) |
03984308 BW |
1446 | |
1447 | (define_insn "indirect_jump_internal" | |
1448 | [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
1449 | "" | |
13fb3a61 | 1450 | "jx\t%0" |
03984308 BW |
1451 | [(set_attr "type" "jump") |
1452 | (set_attr "mode" "none") | |
1453 | (set_attr "length" "3")]) | |
1454 | ||
1455 | ||
1456 | (define_expand "tablejump" | |
1457 | [(use (match_operand:SI 0 "register_operand" "")) | |
1458 | (use (label_ref (match_operand 1 "" "")))] | |
1459 | "" | |
03984308 BW |
1460 | { |
1461 | rtx target = operands[0]; | |
1462 | if (flag_pic) | |
1463 | { | |
13fb3a61 | 1464 | /* For PIC, the table entry is relative to the start of the table. */ |
03984308 BW |
1465 | rtx label = gen_reg_rtx (SImode); |
1466 | target = gen_reg_rtx (SImode); | |
1467 | emit_move_insn (label, gen_rtx_LABEL_REF (SImode, operands[1])); | |
1468 | emit_insn (gen_addsi3 (target, operands[0], label)); | |
1469 | } | |
1470 | emit_jump_insn (gen_tablejump_internal (target, operands[1])); | |
1471 | DONE; | |
13fb3a61 | 1472 | }) |
03984308 BW |
1473 | |
1474 | (define_insn "tablejump_internal" | |
1475 | [(set (pc) | |
1476 | (match_operand:SI 0 "register_operand" "r")) | |
1477 | (use (label_ref (match_operand 1 "" "")))] | |
1478 | "" | |
13fb3a61 | 1479 | "jx\t%0" |
03984308 BW |
1480 | [(set_attr "type" "jump") |
1481 | (set_attr "mode" "none") | |
1482 | (set_attr "length" "3")]) | |
1483 | ||
13fb3a61 BW |
1484 | \f |
1485 | ;; Function calls. | |
03984308 BW |
1486 | |
1487 | (define_expand "sym_PLT" | |
1488 | [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PLT))] | |
1489 | "" | |
1490 | "") | |
1491 | ||
1492 | (define_expand "call" | |
1493 | [(call (match_operand 0 "memory_operand" "") | |
1494 | (match_operand 1 "" ""))] | |
1495 | "" | |
03984308 BW |
1496 | { |
1497 | rtx addr = XEXP (operands[0], 0); | |
f1dfe704 BW |
1498 | if (flag_pic && GET_CODE (addr) == SYMBOL_REF |
1499 | && (!SYMBOL_REF_LOCAL_P (addr) || SYMBOL_REF_EXTERNAL_P (addr))) | |
03984308 BW |
1500 | addr = gen_sym_PLT (addr); |
1501 | if (!call_insn_operand (addr, VOIDmode)) | |
1502 | XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr); | |
13fb3a61 | 1503 | }) |
03984308 BW |
1504 | |
1505 | (define_insn "call_internal" | |
887af464 BW |
1506 | [(call (mem (match_operand:SI 0 "call_insn_operand" "nir")) |
1507 | (match_operand 1 "" "i"))] | |
03984308 | 1508 | "" |
13fb3a61 BW |
1509 | { |
1510 | return xtensa_emit_call (0, operands); | |
1511 | } | |
03984308 BW |
1512 | [(set_attr "type" "call") |
1513 | (set_attr "mode" "none") | |
1514 | (set_attr "length" "3")]) | |
1515 | ||
1516 | (define_expand "call_value" | |
1517 | [(set (match_operand 0 "register_operand" "") | |
1518 | (call (match_operand 1 "memory_operand" "") | |
1519 | (match_operand 2 "" "")))] | |
1520 | "" | |
03984308 BW |
1521 | { |
1522 | rtx addr = XEXP (operands[1], 0); | |
f1dfe704 BW |
1523 | if (flag_pic && GET_CODE (addr) == SYMBOL_REF |
1524 | && (!SYMBOL_REF_LOCAL_P (addr) || SYMBOL_REF_EXTERNAL_P (addr))) | |
03984308 BW |
1525 | addr = gen_sym_PLT (addr); |
1526 | if (!call_insn_operand (addr, VOIDmode)) | |
1527 | XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr); | |
13fb3a61 | 1528 | }) |
03984308 | 1529 | |
03984308 | 1530 | (define_insn "call_value_internal" |
887af464 BW |
1531 | [(set (match_operand 0 "register_operand" "=a") |
1532 | (call (mem (match_operand:SI 1 "call_insn_operand" "nir")) | |
1533 | (match_operand 2 "" "i")))] | |
03984308 | 1534 | "" |
13fb3a61 BW |
1535 | { |
1536 | return xtensa_emit_call (1, operands); | |
1537 | } | |
03984308 BW |
1538 | [(set_attr "type" "call") |
1539 | (set_attr "mode" "none") | |
1540 | (set_attr "length" "3")]) | |
1541 | ||
f42f5a1b BW |
1542 | (define_insn "entry" |
1543 | [(set (reg:SI A1_REG) | |
1544 | (unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "i") | |
1545 | (match_operand:SI 1 "const_int_operand" "i")] | |
1546 | UNSPECV_ENTRY))] | |
1547 | "" | |
a81126a5 | 1548 | "entry\tsp, %1" |
f42f5a1b BW |
1549 | [(set_attr "type" "move") |
1550 | (set_attr "mode" "SI") | |
1551 | (set_attr "length" "3")]) | |
1552 | ||
03984308 BW |
1553 | (define_insn "return" |
1554 | [(return) | |
1555 | (use (reg:SI A0_REG))] | |
1556 | "reload_completed" | |
03984308 | 1557 | { |
13fb3a61 BW |
1558 | return (TARGET_DENSITY ? "retw.n" : "retw"); |
1559 | } | |
03984308 BW |
1560 | [(set_attr "type" "jump") |
1561 | (set_attr "mode" "none") | |
1562 | (set_attr "length" "2")]) | |
1563 | ||
13fb3a61 BW |
1564 | \f |
1565 | ;; Miscellaneous instructions. | |
03984308 | 1566 | |
f42f5a1b BW |
1567 | (define_expand "prologue" |
1568 | [(const_int 0)] | |
1569 | "" | |
f42f5a1b BW |
1570 | { |
1571 | xtensa_expand_prologue (); | |
1572 | DONE; | |
13fb3a61 | 1573 | }) |
f42f5a1b BW |
1574 | |
1575 | (define_expand "epilogue" | |
1576 | [(return)] | |
1577 | "" | |
f42f5a1b BW |
1578 | { |
1579 | emit_jump_insn (gen_return ()); | |
1580 | DONE; | |
13fb3a61 | 1581 | }) |
f42f5a1b | 1582 | |
03984308 BW |
1583 | (define_insn "nop" |
1584 | [(const_int 0)] | |
1585 | "" | |
03984308 | 1586 | { |
13fb3a61 BW |
1587 | return (TARGET_DENSITY ? "nop.n" : "nop"); |
1588 | } | |
03984308 BW |
1589 | [(set_attr "type" "nop") |
1590 | (set_attr "mode" "none") | |
1591 | (set_attr "length" "3")]) | |
1592 | ||
1593 | (define_expand "nonlocal_goto" | |
1594 | [(match_operand:SI 0 "general_operand" "") | |
1595 | (match_operand:SI 1 "general_operand" "") | |
1596 | (match_operand:SI 2 "general_operand" "") | |
1597 | (match_operand:SI 3 "" "")] | |
1598 | "" | |
03984308 BW |
1599 | { |
1600 | xtensa_expand_nonlocal_goto (operands); | |
1601 | DONE; | |
13fb3a61 | 1602 | }) |
03984308 BW |
1603 | |
1604 | ;; Setting up a frame pointer is tricky for Xtensa because GCC doesn't | |
1605 | ;; know if a frame pointer is required until the reload pass, and | |
1606 | ;; because there may be an incoming argument value in the hard frame | |
13fb3a61 | 1607 | ;; pointer register (a7). If there is an incoming argument in that |
03984308 BW |
1608 | ;; register, the "set_frame_ptr" insn gets inserted immediately after |
1609 | ;; the insn that copies the incoming argument to a pseudo or to the | |
1610 | ;; stack. This serves several purposes here: (1) it keeps the | |
1611 | ;; optimizer from copy-propagating or scheduling the use of a7 as an | |
1612 | ;; incoming argument away from the beginning of the function; (2) we | |
1613 | ;; can use a post-reload splitter to expand away the insn if a frame | |
1614 | ;; pointer is not required, so that the post-reload scheduler can do | |
13fb3a61 BW |
1615 | ;; the right thing; and (3) it makes it easy for the prologue expander |
1616 | ;; to search for this insn to determine whether it should add a new insn | |
03984308 BW |
1617 | ;; to set up the frame pointer. |
1618 | ||
1619 | (define_insn "set_frame_ptr" | |
f42f5a1b | 1620 | [(set (reg:SI A7_REG) (unspec_volatile:SI [(const_int 0)] UNSPECV_SET_FP))] |
03984308 | 1621 | "" |
03984308 BW |
1622 | { |
1623 | if (frame_pointer_needed) | |
13fb3a61 BW |
1624 | return "mov\ta7, sp"; |
1625 | return ""; | |
1626 | } | |
03984308 BW |
1627 | [(set_attr "type" "move") |
1628 | (set_attr "mode" "SI") | |
1629 | (set_attr "length" "3")]) | |
1630 | ||
1631 | ;; Post-reload splitter to remove fp assignment when it's not needed. | |
1632 | (define_split | |
f42f5a1b | 1633 | [(set (reg:SI A7_REG) (unspec_volatile:SI [(const_int 0)] UNSPECV_SET_FP))] |
03984308 BW |
1634 | "reload_completed && !frame_pointer_needed" |
1635 | [(unspec [(const_int 0)] UNSPEC_NOP)] | |
1636 | "") | |
1637 | ||
1638 | ;; The preceding splitter needs something to split the insn into; | |
1639 | ;; things start breaking if the result is just a "use" so instead we | |
1640 | ;; generate the following insn. | |
3219c65b | 1641 | (define_insn "*unspec_nop" |
03984308 BW |
1642 | [(unspec [(const_int 0)] UNSPEC_NOP)] |
1643 | "" | |
1644 | "" | |
1645 | [(set_attr "type" "nop") | |
1646 | (set_attr "mode" "none") | |
1647 | (set_attr "length" "0")]) | |
1648 | ||
0c14a54d BW |
1649 | ;; The fix_return_addr pattern sets the high 2 bits of an address in a |
1650 | ;; register to match the high bits of the current PC. | |
0c14a54d BW |
1651 | (define_insn "fix_return_addr" |
1652 | [(set (match_operand:SI 0 "register_operand" "=a") | |
1653 | (unspec:SI [(match_operand:SI 1 "register_operand" "r")] | |
1654 | UNSPEC_RET_ADDR)) | |
1655 | (clobber (match_scratch:SI 2 "=r")) | |
1656 | (clobber (match_scratch:SI 3 "=r"))] | |
1657 | "" | |
13fb3a61 BW |
1658 | "mov\t%2, a0\;call0\t0f\;.align\t4\;0:\;mov\t%3, a0\;mov\ta0, %2\;\ |
1659 | srli\t%3, %3, 30\;slli\t%0, %1, 2\;ssai\t2\;src\t%0, %3, %0" | |
0c14a54d BW |
1660 | [(set_attr "type" "multi") |
1661 | (set_attr "mode" "SI") | |
1662 | (set_attr "length" "24")]) | |
1663 | ||
13fb3a61 BW |
1664 | \f |
1665 | ;; Instructions for the Xtensa "boolean" option. | |
03984308 | 1666 | |
3219c65b | 1667 | (define_insn "*booltrue" |
03984308 BW |
1668 | [(set (pc) |
1669 | (if_then_else (match_operator 2 "boolean_operator" | |
1670 | [(match_operand:CC 0 "register_operand" "b") | |
1671 | (const_int 0)]) | |
1672 | (label_ref (match_operand 1 "" "")) | |
1673 | (pc)))] | |
1674 | "TARGET_BOOLEANS" | |
03984308 BW |
1675 | { |
1676 | if (GET_CODE (operands[2]) == EQ) | |
13fb3a61 | 1677 | return "bf\t%0, %1"; |
03984308 | 1678 | else |
13fb3a61 BW |
1679 | return "bt\t%0, %1"; |
1680 | } | |
03984308 BW |
1681 | [(set_attr "type" "jump") |
1682 | (set_attr "mode" "none") | |
1683 | (set_attr "length" "3")]) | |
1684 | ||
3219c65b | 1685 | (define_insn "*boolfalse" |
03984308 BW |
1686 | [(set (pc) |
1687 | (if_then_else (match_operator 2 "boolean_operator" | |
1688 | [(match_operand:CC 0 "register_operand" "b") | |
1689 | (const_int 0)]) | |
1690 | (pc) | |
1691 | (label_ref (match_operand 1 "" ""))))] | |
1692 | "TARGET_BOOLEANS" | |
03984308 BW |
1693 | { |
1694 | if (GET_CODE (operands[2]) == EQ) | |
13fb3a61 | 1695 | return "bt\t%0, %1"; |
03984308 | 1696 | else |
13fb3a61 BW |
1697 | return "bf\t%0, %1"; |
1698 | } | |
03984308 BW |
1699 | [(set_attr "type" "jump") |
1700 | (set_attr "mode" "none") | |
1701 | (set_attr "length" "3")]) | |
2a48b790 BW |
1702 | |
1703 | \f | |
1704 | ;; Atomic operations | |
1705 | ||
1706 | (define_expand "memory_barrier" | |
1707 | [(set (mem:BLK (match_dup 0)) | |
1708 | (unspec_volatile:BLK [(mem:BLK (match_dup 0))] UNSPECV_MEMW))] | |
1709 | "" | |
1710 | { | |
1711 | operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (SImode)); | |
1712 | MEM_VOLATILE_P (operands[0]) = 1; | |
1713 | }) | |
1714 | ||
1715 | (define_insn "*memory_barrier" | |
1716 | [(set (match_operand:BLK 0 "" "") | |
1717 | (unspec_volatile:BLK [(match_operand:BLK 1 "" "")] UNSPECV_MEMW))] | |
1718 | "" | |
1719 | "memw" | |
1720 | [(set_attr "type" "unknown") | |
1721 | (set_attr "mode" "none") | |
1722 | (set_attr "length" "3")]) | |
1723 | ||
1724 | ;; sync_lock_release is only implemented for SImode. | |
1725 | ;; For other modes, just use the default of a store with a memory_barrier. | |
1726 | (define_insn "sync_lock_releasesi" | |
1727 | [(set (match_operand:SI 0 "mem_operand" "=U") | |
1728 | (unspec_volatile:SI | |
1729 | [(match_operand:SI 1 "register_operand" "r")] | |
1730 | UNSPECV_S32RI))] | |
1731 | "TARGET_RELEASE_SYNC" | |
1732 | "s32ri\t%1, %0" | |
1733 | [(set_attr "type" "store") | |
1734 | (set_attr "mode" "SI") | |
1735 | (set_attr "length" "3")]) | |
1736 | ||
1737 | (define_insn "sync_compare_and_swapsi" | |
1738 | [(parallel | |
1739 | [(set (match_operand:SI 0 "register_operand" "=a") | |
1740 | (match_operand:SI 1 "mem_operand" "+U")) | |
1741 | (set (match_dup 1) | |
1742 | (unspec_volatile:SI | |
1743 | [(match_dup 1) | |
1744 | (match_operand:SI 2 "register_operand" "r") | |
1745 | (match_operand:SI 3 "register_operand" "0")] | |
1746 | UNSPECV_S32C1I))])] | |
1747 | "TARGET_S32C1I" | |
1748 | "wsr\t%2, SCOMPARE1\;s32c1i\t%3, %1" | |
1749 | [(set_attr "type" "multi") | |
1750 | (set_attr "mode" "SI") | |
1751 | (set_attr "length" "6")]) | |
1752 | ||
1753 | (define_expand "sync_compare_and_swap<mode>" | |
1754 | [(parallel | |
1755 | [(set (match_operand:HQI 0 "register_operand" "") | |
1756 | (match_operand:HQI 1 "mem_operand" "")) | |
1757 | (set (match_dup 1) | |
1758 | (unspec_volatile:HQI | |
1759 | [(match_dup 1) | |
1760 | (match_operand:HQI 2 "register_operand" "") | |
1761 | (match_operand:HQI 3 "register_operand" "")] | |
1762 | UNSPECV_S32C1I))])] | |
1763 | "TARGET_S32C1I" | |
1764 | { | |
1765 | xtensa_expand_compare_and_swap (operands[0], operands[1], | |
1766 | operands[2], operands[3]); | |
1767 | DONE; | |
1768 | }) | |
1769 | ||
1770 | (define_expand "sync_lock_test_and_set<mode>" | |
1771 | [(match_operand:HQI 0 "register_operand") | |
1772 | (match_operand:HQI 1 "memory_operand") | |
1773 | (match_operand:HQI 2 "register_operand")] | |
1774 | "TARGET_S32C1I" | |
1775 | { | |
1776 | xtensa_expand_atomic (SET, operands[0], operands[1], operands[2], false); | |
1777 | DONE; | |
1778 | }) | |
1779 | ||
1780 | (define_expand "sync_<atomic><mode>" | |
1781 | [(set (match_operand:HQI 0 "memory_operand") | |
1782 | (ATOMIC:HQI (match_dup 0) | |
1783 | (match_operand:HQI 1 "register_operand")))] | |
1784 | "TARGET_S32C1I" | |
1785 | { | |
1786 | xtensa_expand_atomic (<CODE>, NULL_RTX, operands[0], operands[1], false); | |
1787 | DONE; | |
1788 | }) | |
1789 | ||
1790 | (define_expand "sync_old_<atomic><mode>" | |
1791 | [(set (match_operand:HQI 0 "register_operand") | |
1792 | (match_operand:HQI 1 "memory_operand")) | |
1793 | (set (match_dup 1) | |
1794 | (ATOMIC:HQI (match_dup 1) | |
1795 | (match_operand:HQI 2 "register_operand")))] | |
1796 | "TARGET_S32C1I" | |
1797 | { | |
1798 | xtensa_expand_atomic (<CODE>, operands[0], operands[1], operands[2], false); | |
1799 | DONE; | |
1800 | }) | |
1801 | ||
1802 | (define_expand "sync_new_<atomic><mode>" | |
1803 | [(set (match_operand:HQI 0 "register_operand") | |
1804 | (ATOMIC:HQI (match_operand:HQI 1 "memory_operand") | |
1805 | (match_operand:HQI 2 "register_operand"))) | |
1806 | (set (match_dup 1) (ATOMIC:HQI (match_dup 1) (match_dup 2)))] | |
1807 | "TARGET_S32C1I" | |
1808 | { | |
1809 | xtensa_expand_atomic (<CODE>, operands[0], operands[1], operands[2], true); | |
1810 | DONE; | |
1811 | }) |