Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/mips/mips.md @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 ;; Mips.md Machine Description for MIPS based processors | |
2 ;; Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, | |
3 ;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 | |
4 ;; Free Software Foundation, Inc. | |
5 ;; Contributed by A. Lichnewsky, lich@inria.inria.fr | |
6 ;; Changes by Michael Meissner, meissner@osf.org | |
7 ;; 64-bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and | |
8 ;; Brendan Eich, brendan@microunity.com. | |
9 | |
10 ;; This file is part of GCC. | |
11 | |
12 ;; GCC is free software; you can redistribute it and/or modify | |
13 ;; it under the terms of the GNU General Public License as published by | |
14 ;; the Free Software Foundation; either version 3, or (at your option) | |
15 ;; any later version. | |
16 | |
17 ;; GCC is distributed in the hope that it will be useful, | |
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 ;; GNU General Public License for more details. | |
21 | |
22 ;; You should have received a copy of the GNU General Public License | |
23 ;; along with GCC; see the file COPYING3. If not see | |
24 ;; <http://www.gnu.org/licenses/>. | |
25 | |
26 (define_constants | |
27 [(UNSPEC_LOAD_LOW 0) | |
28 (UNSPEC_LOAD_HIGH 1) | |
29 (UNSPEC_STORE_WORD 2) | |
30 (UNSPEC_GET_FNADDR 3) | |
31 (UNSPEC_BLOCKAGE 4) | |
32 (UNSPEC_CPRESTORE 5) | |
33 (UNSPEC_RESTORE_GP 6) | |
34 (UNSPEC_EH_RETURN 7) | |
35 (UNSPEC_CONSTTABLE_INT 8) | |
36 (UNSPEC_CONSTTABLE_FLOAT 9) | |
37 (UNSPEC_ALIGN 14) | |
38 (UNSPEC_HIGH 17) | |
39 (UNSPEC_LOAD_LEFT 18) | |
40 (UNSPEC_LOAD_RIGHT 19) | |
41 (UNSPEC_STORE_LEFT 20) | |
42 (UNSPEC_STORE_RIGHT 21) | |
43 (UNSPEC_LOADGP 22) | |
44 (UNSPEC_LOAD_CALL 23) | |
45 (UNSPEC_LOAD_GOT 24) | |
46 (UNSPEC_GP 25) | |
47 (UNSPEC_MFHI 26) | |
48 (UNSPEC_MTHI 27) | |
49 (UNSPEC_SET_HILO 28) | |
50 (UNSPEC_TLS_LDM 29) | |
51 (UNSPEC_TLS_GET_TP 30) | |
52 (UNSPEC_MFHC1 31) | |
53 (UNSPEC_MTHC1 32) | |
54 (UNSPEC_CLEAR_HAZARD 33) | |
55 (UNSPEC_RDHWR 34) | |
56 (UNSPEC_SYNCI 35) | |
57 (UNSPEC_SYNC 36) | |
58 (UNSPEC_COMPARE_AND_SWAP 37) | |
59 (UNSPEC_COMPARE_AND_SWAP_12 38) | |
60 (UNSPEC_SYNC_OLD_OP 39) | |
61 (UNSPEC_SYNC_NEW_OP 40) | |
62 (UNSPEC_SYNC_NEW_OP_12 41) | |
63 (UNSPEC_SYNC_OLD_OP_12 42) | |
64 (UNSPEC_SYNC_EXCHANGE 43) | |
65 (UNSPEC_SYNC_EXCHANGE_12 44) | |
66 (UNSPEC_MEMORY_BARRIER 45) | |
67 (UNSPEC_SET_GOT_VERSION 46) | |
68 (UNSPEC_UPDATE_GOT_VERSION 47) | |
69 (UNSPEC_COPYGP 48) | |
70 | |
71 (UNSPEC_ADDRESS_FIRST 100) | |
72 | |
73 (TLS_GET_TP_REGNUM 3) | |
74 (GOT_VERSION_REGNUM 79) | |
75 | |
76 ;; For MIPS Paired-Singled Floating Point Instructions. | |
77 | |
78 (UNSPEC_MOVE_TF_PS 200) | |
79 (UNSPEC_C 201) | |
80 | |
81 ;; MIPS64/MIPS32R2 alnv.ps | |
82 (UNSPEC_ALNV_PS 202) | |
83 | |
84 ;; MIPS-3D instructions | |
85 (UNSPEC_CABS 203) | |
86 | |
87 (UNSPEC_ADDR_PS 204) | |
88 (UNSPEC_CVT_PW_PS 205) | |
89 (UNSPEC_CVT_PS_PW 206) | |
90 (UNSPEC_MULR_PS 207) | |
91 (UNSPEC_ABS_PS 208) | |
92 | |
93 (UNSPEC_RSQRT1 209) | |
94 (UNSPEC_RSQRT2 210) | |
95 (UNSPEC_RECIP1 211) | |
96 (UNSPEC_RECIP2 212) | |
97 (UNSPEC_SINGLE_CC 213) | |
98 (UNSPEC_SCC 214) | |
99 | |
100 ;; MIPS DSP ASE Revision 0.98 3/24/2005 | |
101 (UNSPEC_ADDQ 300) | |
102 (UNSPEC_ADDQ_S 301) | |
103 (UNSPEC_SUBQ 302) | |
104 (UNSPEC_SUBQ_S 303) | |
105 (UNSPEC_ADDSC 304) | |
106 (UNSPEC_ADDWC 305) | |
107 (UNSPEC_MODSUB 306) | |
108 (UNSPEC_RADDU_W_QB 307) | |
109 (UNSPEC_ABSQ_S 308) | |
110 (UNSPEC_PRECRQ_QB_PH 309) | |
111 (UNSPEC_PRECRQ_PH_W 310) | |
112 (UNSPEC_PRECRQ_RS_PH_W 311) | |
113 (UNSPEC_PRECRQU_S_QB_PH 312) | |
114 (UNSPEC_PRECEQ_W_PHL 313) | |
115 (UNSPEC_PRECEQ_W_PHR 314) | |
116 (UNSPEC_PRECEQU_PH_QBL 315) | |
117 (UNSPEC_PRECEQU_PH_QBR 316) | |
118 (UNSPEC_PRECEQU_PH_QBLA 317) | |
119 (UNSPEC_PRECEQU_PH_QBRA 318) | |
120 (UNSPEC_PRECEU_PH_QBL 319) | |
121 (UNSPEC_PRECEU_PH_QBR 320) | |
122 (UNSPEC_PRECEU_PH_QBLA 321) | |
123 (UNSPEC_PRECEU_PH_QBRA 322) | |
124 (UNSPEC_SHLL 323) | |
125 (UNSPEC_SHLL_S 324) | |
126 (UNSPEC_SHRL_QB 325) | |
127 (UNSPEC_SHRA_PH 326) | |
128 (UNSPEC_SHRA_R 327) | |
129 (UNSPEC_MULEU_S_PH_QBL 328) | |
130 (UNSPEC_MULEU_S_PH_QBR 329) | |
131 (UNSPEC_MULQ_RS_PH 330) | |
132 (UNSPEC_MULEQ_S_W_PHL 331) | |
133 (UNSPEC_MULEQ_S_W_PHR 332) | |
134 (UNSPEC_DPAU_H_QBL 333) | |
135 (UNSPEC_DPAU_H_QBR 334) | |
136 (UNSPEC_DPSU_H_QBL 335) | |
137 (UNSPEC_DPSU_H_QBR 336) | |
138 (UNSPEC_DPAQ_S_W_PH 337) | |
139 (UNSPEC_DPSQ_S_W_PH 338) | |
140 (UNSPEC_MULSAQ_S_W_PH 339) | |
141 (UNSPEC_DPAQ_SA_L_W 340) | |
142 (UNSPEC_DPSQ_SA_L_W 341) | |
143 (UNSPEC_MAQ_S_W_PHL 342) | |
144 (UNSPEC_MAQ_S_W_PHR 343) | |
145 (UNSPEC_MAQ_SA_W_PHL 344) | |
146 (UNSPEC_MAQ_SA_W_PHR 345) | |
147 (UNSPEC_BITREV 346) | |
148 (UNSPEC_INSV 347) | |
149 (UNSPEC_REPL_QB 348) | |
150 (UNSPEC_REPL_PH 349) | |
151 (UNSPEC_CMP_EQ 350) | |
152 (UNSPEC_CMP_LT 351) | |
153 (UNSPEC_CMP_LE 352) | |
154 (UNSPEC_CMPGU_EQ_QB 353) | |
155 (UNSPEC_CMPGU_LT_QB 354) | |
156 (UNSPEC_CMPGU_LE_QB 355) | |
157 (UNSPEC_PICK 356) | |
158 (UNSPEC_PACKRL_PH 357) | |
159 (UNSPEC_EXTR_W 358) | |
160 (UNSPEC_EXTR_R_W 359) | |
161 (UNSPEC_EXTR_RS_W 360) | |
162 (UNSPEC_EXTR_S_H 361) | |
163 (UNSPEC_EXTP 362) | |
164 (UNSPEC_EXTPDP 363) | |
165 (UNSPEC_SHILO 364) | |
166 (UNSPEC_MTHLIP 365) | |
167 (UNSPEC_WRDSP 366) | |
168 (UNSPEC_RDDSP 367) | |
169 | |
170 ;; MIPS DSP ASE REV 2 Revision 0.02 11/24/2006 | |
171 (UNSPEC_ABSQ_S_QB 400) | |
172 (UNSPEC_ADDU_PH 401) | |
173 (UNSPEC_ADDU_S_PH 402) | |
174 (UNSPEC_ADDUH_QB 403) | |
175 (UNSPEC_ADDUH_R_QB 404) | |
176 (UNSPEC_APPEND 405) | |
177 (UNSPEC_BALIGN 406) | |
178 (UNSPEC_CMPGDU_EQ_QB 407) | |
179 (UNSPEC_CMPGDU_LT_QB 408) | |
180 (UNSPEC_CMPGDU_LE_QB 409) | |
181 (UNSPEC_DPA_W_PH 410) | |
182 (UNSPEC_DPS_W_PH 411) | |
183 (UNSPEC_MADD 412) | |
184 (UNSPEC_MADDU 413) | |
185 (UNSPEC_MSUB 414) | |
186 (UNSPEC_MSUBU 415) | |
187 (UNSPEC_MUL_PH 416) | |
188 (UNSPEC_MUL_S_PH 417) | |
189 (UNSPEC_MULQ_RS_W 418) | |
190 (UNSPEC_MULQ_S_PH 419) | |
191 (UNSPEC_MULQ_S_W 420) | |
192 (UNSPEC_MULSA_W_PH 421) | |
193 (UNSPEC_MULT 422) | |
194 (UNSPEC_MULTU 423) | |
195 (UNSPEC_PRECR_QB_PH 424) | |
196 (UNSPEC_PRECR_SRA_PH_W 425) | |
197 (UNSPEC_PRECR_SRA_R_PH_W 426) | |
198 (UNSPEC_PREPEND 427) | |
199 (UNSPEC_SHRA_QB 428) | |
200 (UNSPEC_SHRA_R_QB 429) | |
201 (UNSPEC_SHRL_PH 430) | |
202 (UNSPEC_SUBU_PH 431) | |
203 (UNSPEC_SUBU_S_PH 432) | |
204 (UNSPEC_SUBUH_QB 433) | |
205 (UNSPEC_SUBUH_R_QB 434) | |
206 (UNSPEC_ADDQH_PH 435) | |
207 (UNSPEC_ADDQH_R_PH 436) | |
208 (UNSPEC_ADDQH_W 437) | |
209 (UNSPEC_ADDQH_R_W 438) | |
210 (UNSPEC_SUBQH_PH 439) | |
211 (UNSPEC_SUBQH_R_PH 440) | |
212 (UNSPEC_SUBQH_W 441) | |
213 (UNSPEC_SUBQH_R_W 442) | |
214 (UNSPEC_DPAX_W_PH 443) | |
215 (UNSPEC_DPSX_W_PH 444) | |
216 (UNSPEC_DPAQX_S_W_PH 445) | |
217 (UNSPEC_DPAQX_SA_W_PH 446) | |
218 (UNSPEC_DPSQX_S_W_PH 447) | |
219 (UNSPEC_DPSQX_SA_W_PH 448) | |
220 | |
221 ;; ST Microelectronics Loongson-2E/2F. | |
222 (UNSPEC_LOONGSON_PAVG 500) | |
223 (UNSPEC_LOONGSON_PCMPEQ 501) | |
224 (UNSPEC_LOONGSON_PCMPGT 502) | |
225 (UNSPEC_LOONGSON_PEXTR 503) | |
226 (UNSPEC_LOONGSON_PINSR_0 504) | |
227 (UNSPEC_LOONGSON_PINSR_1 505) | |
228 (UNSPEC_LOONGSON_PINSR_2 506) | |
229 (UNSPEC_LOONGSON_PINSR_3 507) | |
230 (UNSPEC_LOONGSON_PMADD 508) | |
231 (UNSPEC_LOONGSON_PMOVMSK 509) | |
232 (UNSPEC_LOONGSON_PMULHU 510) | |
233 (UNSPEC_LOONGSON_PMULH 511) | |
234 (UNSPEC_LOONGSON_PMULL 512) | |
235 (UNSPEC_LOONGSON_PMULU 513) | |
236 (UNSPEC_LOONGSON_PASUBUB 514) | |
237 (UNSPEC_LOONGSON_BIADD 515) | |
238 (UNSPEC_LOONGSON_PSADBH 516) | |
239 (UNSPEC_LOONGSON_PSHUFH 517) | |
240 (UNSPEC_LOONGSON_PUNPCKH 518) | |
241 (UNSPEC_LOONGSON_PUNPCKL 519) | |
242 (UNSPEC_LOONGSON_PADDD 520) | |
243 (UNSPEC_LOONGSON_PSUBD 521) | |
244 | |
245 ;; Used in loongson2ef.md | |
246 (UNSPEC_LOONGSON_ALU1_TURN_ENABLED_INSN 530) | |
247 (UNSPEC_LOONGSON_ALU2_TURN_ENABLED_INSN 531) | |
248 (UNSPEC_LOONGSON_FALU1_TURN_ENABLED_INSN 532) | |
249 (UNSPEC_LOONGSON_FALU2_TURN_ENABLED_INSN 533) | |
250 | |
251 (UNSPEC_MIPS_CACHE 600) | |
252 (UNSPEC_R10K_CACHE_BARRIER 601) | |
253 ] | |
254 ) | |
255 | |
256 (include "predicates.md") | |
257 (include "constraints.md") | |
258 | |
259 ;; .................... | |
260 ;; | |
261 ;; Attributes | |
262 ;; | |
263 ;; .................... | |
264 | |
265 (define_attr "got" "unset,xgot_high,load" | |
266 (const_string "unset")) | |
267 | |
268 ;; For jal instructions, this attribute is DIRECT when the target address | |
269 ;; is symbolic and INDIRECT when it is a register. | |
270 (define_attr "jal" "unset,direct,indirect" | |
271 (const_string "unset")) | |
272 | |
273 ;; This attribute is YES if the instruction is a jal macro (not a | |
274 ;; real jal instruction). | |
275 ;; | |
276 ;; jal is always a macro for TARGET_CALL_CLOBBERED_GP because it includes | |
277 ;; an instruction to restore $gp. Direct jals are also macros for | |
278 ;; flag_pic && !TARGET_ABSOLUTE_ABICALLS because they first load | |
279 ;; the target address into a register. | |
280 (define_attr "jal_macro" "no,yes" | |
281 (cond [(eq_attr "jal" "direct") | |
282 (symbol_ref "TARGET_CALL_CLOBBERED_GP | |
283 || (flag_pic && !TARGET_ABSOLUTE_ABICALLS)") | |
284 (eq_attr "jal" "indirect") | |
285 (symbol_ref "TARGET_CALL_CLOBBERED_GP")] | |
286 (const_string "no"))) | |
287 | |
288 ;; Classification of moves, extensions and truncations. Most values | |
289 ;; are as for "type" (see below) but there are also the following | |
290 ;; move-specific values: | |
291 ;; | |
292 ;; constN move an N-constraint integer into a MIPS16 register | |
293 ;; sll0 "sll DEST,SRC,0", which on 64-bit targets is guaranteed | |
294 ;; to produce a sign-extended DEST, even if SRC is not | |
295 ;; properly sign-extended | |
296 ;; andi a single ANDI instruction | |
297 ;; loadpool move a constant into a MIPS16 register by loading it | |
298 ;; from the pool | |
299 ;; shift_shift a shift left followed by a shift right | |
300 ;; lui_movf an LUI followed by a MOVF (for d<-z CC moves) | |
301 ;; | |
302 ;; This attribute is used to determine the instruction's length and | |
303 ;; scheduling type. For doubleword moves, the attribute always describes | |
304 ;; the split instructions; in some cases, it is more appropriate for the | |
305 ;; scheduling type to be "multi" instead. | |
306 (define_attr "move_type" | |
307 "unknown,load,fpload,store,fpstore,mtc,mfc,mthilo,mfhilo,move,fmove, | |
308 const,constN,signext,sll0,andi,loadpool,shift_shift,lui_movf" | |
309 (const_string "unknown")) | |
310 | |
311 ;; Main data type used by the insn | |
312 (define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF,FPSW" | |
313 (const_string "unknown")) | |
314 | |
315 ;; True if the main data type is twice the size of a word. | |
316 (define_attr "dword_mode" "no,yes" | |
317 (cond [(and (eq_attr "mode" "DI,DF") | |
318 (eq (symbol_ref "TARGET_64BIT") (const_int 0))) | |
319 (const_string "yes") | |
320 | |
321 (and (eq_attr "mode" "TI,TF") | |
322 (ne (symbol_ref "TARGET_64BIT") (const_int 0))) | |
323 (const_string "yes")] | |
324 (const_string "no"))) | |
325 | |
326 ;; Classification of each insn. | |
327 ;; branch conditional branch | |
328 ;; jump unconditional jump | |
329 ;; call unconditional call | |
330 ;; load load instruction(s) | |
331 ;; fpload floating point load | |
332 ;; fpidxload floating point indexed load | |
333 ;; store store instruction(s) | |
334 ;; fpstore floating point store | |
335 ;; fpidxstore floating point indexed store | |
336 ;; prefetch memory prefetch (register + offset) | |
337 ;; prefetchx memory indexed prefetch (register + register) | |
338 ;; condmove conditional moves | |
339 ;; mtc transfer to coprocessor | |
340 ;; mfc transfer from coprocessor | |
341 ;; mthilo transfer to hi/lo registers | |
342 ;; mfhilo transfer from hi/lo registers | |
343 ;; const load constant | |
344 ;; arith integer arithmetic instructions | |
345 ;; logical integer logical instructions | |
346 ;; shift integer shift instructions | |
347 ;; slt set less than instructions | |
348 ;; signext sign extend instructions | |
349 ;; clz the clz and clo instructions | |
350 ;; pop the pop instruction | |
351 ;; trap trap if instructions | |
352 ;; imul integer multiply 2 operands | |
353 ;; imul3 integer multiply 3 operands | |
354 ;; imul3nc integer multiply 3 operands without clobbering HI/LO | |
355 ;; imadd integer multiply-add | |
356 ;; idiv integer divide 2 operands | |
357 ;; idiv3 integer divide 3 operands | |
358 ;; move integer register move ({,D}ADD{,U} with rt = 0) | |
359 ;; fmove floating point register move | |
360 ;; fadd floating point add/subtract | |
361 ;; fmul floating point multiply | |
362 ;; fmadd floating point multiply-add | |
363 ;; fdiv floating point divide | |
364 ;; frdiv floating point reciprocal divide | |
365 ;; frdiv1 floating point reciprocal divide step 1 | |
366 ;; frdiv2 floating point reciprocal divide step 2 | |
367 ;; fabs floating point absolute value | |
368 ;; fneg floating point negation | |
369 ;; fcmp floating point compare | |
370 ;; fcvt floating point convert | |
371 ;; fsqrt floating point square root | |
372 ;; frsqrt floating point reciprocal square root | |
373 ;; frsqrt1 floating point reciprocal square root step1 | |
374 ;; frsqrt2 floating point reciprocal square root step2 | |
375 ;; multi multiword sequence (or user asm statements) | |
376 ;; nop no operation | |
377 ;; ghost an instruction that produces no real code | |
378 (define_attr "type" | |
379 "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore, | |
380 prefetch,prefetchx,condmove,mtc,mfc,mthilo,mfhilo,const,arith,logical, | |
381 shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,move, | |
382 fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt, | |
383 frsqrt,frsqrt1,frsqrt2,multi,nop,ghost" | |
384 (cond [(eq_attr "jal" "!unset") (const_string "call") | |
385 (eq_attr "got" "load") (const_string "load") | |
386 | |
387 ;; If a doubleword move uses these expensive instructions, | |
388 ;; it is usually better to schedule them in the same way | |
389 ;; as the singleword form, rather than as "multi". | |
390 (eq_attr "move_type" "load") (const_string "load") | |
391 (eq_attr "move_type" "fpload") (const_string "fpload") | |
392 (eq_attr "move_type" "store") (const_string "store") | |
393 (eq_attr "move_type" "fpstore") (const_string "fpstore") | |
394 (eq_attr "move_type" "mtc") (const_string "mtc") | |
395 (eq_attr "move_type" "mfc") (const_string "mfc") | |
396 (eq_attr "move_type" "mthilo") (const_string "mthilo") | |
397 (eq_attr "move_type" "mfhilo") (const_string "mfhilo") | |
398 | |
399 ;; These types of move are always single insns. | |
400 (eq_attr "move_type" "fmove") (const_string "fmove") | |
401 (eq_attr "move_type" "loadpool") (const_string "load") | |
402 (eq_attr "move_type" "signext") (const_string "signext") | |
403 (eq_attr "move_type" "sll0") (const_string "shift") | |
404 (eq_attr "move_type" "andi") (const_string "logical") | |
405 | |
406 ;; These types of move are always split. | |
407 (eq_attr "move_type" "constN,shift_shift") | |
408 (const_string "multi") | |
409 | |
410 ;; These types of move are split for doubleword modes only. | |
411 (and (eq_attr "move_type" "move,const") | |
412 (eq_attr "dword_mode" "yes")) | |
413 (const_string "multi") | |
414 (eq_attr "move_type" "move") (const_string "move") | |
415 (eq_attr "move_type" "const") (const_string "const")] | |
416 ;; We classify "lui_movf" as "unknown" rather than "multi" | |
417 ;; because we don't split it. FIXME: we should split instead. | |
418 (const_string "unknown"))) | |
419 | |
420 ;; Mode for conversion types (fcvt) | |
421 ;; I2S integer to float single (SI/DI to SF) | |
422 ;; I2D integer to float double (SI/DI to DF) | |
423 ;; S2I float to integer (SF to SI/DI) | |
424 ;; D2I float to integer (DF to SI/DI) | |
425 ;; D2S double to float single | |
426 ;; S2D float single to double | |
427 | |
428 (define_attr "cnv_mode" "unknown,I2S,I2D,S2I,D2I,D2S,S2D" | |
429 (const_string "unknown")) | |
430 | |
431 ;; Is this an extended instruction in mips16 mode? | |
432 (define_attr "extended_mips16" "no,yes" | |
433 (if_then_else (ior (eq_attr "move_type" "sll0") | |
434 (eq_attr "type" "branch") | |
435 (eq_attr "jal" "direct")) | |
436 (const_string "yes") | |
437 (const_string "no"))) | |
438 | |
439 ;; Length of instruction in bytes. | |
440 (define_attr "length" "" | |
441 (cond [(and (eq_attr "extended_mips16" "yes") | |
442 (ne (symbol_ref "TARGET_MIPS16") (const_int 0))) | |
443 (const_int 8) | |
444 | |
445 ;; Direct branch instructions have a range of [-0x40000,0x3fffc]. | |
446 ;; If a branch is outside this range, we have a choice of two | |
447 ;; sequences. For PIC, an out-of-range branch like: | |
448 ;; | |
449 ;; bne r1,r2,target | |
450 ;; dslot | |
451 ;; | |
452 ;; becomes the equivalent of: | |
453 ;; | |
454 ;; beq r1,r2,1f | |
455 ;; dslot | |
456 ;; la $at,target | |
457 ;; jr $at | |
458 ;; nop | |
459 ;; 1: | |
460 ;; | |
461 ;; where the load address can be up to three instructions long | |
462 ;; (lw, nop, addiu). | |
463 ;; | |
464 ;; The non-PIC case is similar except that we use a direct | |
465 ;; jump instead of an la/jr pair. Since the target of this | |
466 ;; jump is an absolute 28-bit bit address (the other bits | |
467 ;; coming from the address of the delay slot) this form cannot | |
468 ;; cross a 256MB boundary. We could provide the option of | |
469 ;; using la/jr in this case too, but we do not do so at | |
470 ;; present. | |
471 ;; | |
472 ;; Note that this value does not account for the delay slot | |
473 ;; instruction, whose length is added separately. If the RTL | |
474 ;; pattern has no explicit delay slot, mips_adjust_insn_length | |
475 ;; will add the length of the implicit nop. The values for | |
476 ;; forward and backward branches will be different as well. | |
477 (eq_attr "type" "branch") | |
478 (cond [(and (le (minus (match_dup 1) (pc)) (const_int 131064)) | |
479 (le (minus (pc) (match_dup 1)) (const_int 131068))) | |
480 (const_int 4) | |
481 (ne (symbol_ref "flag_pic") (const_int 0)) | |
482 (const_int 24) | |
483 ] (const_int 12)) | |
484 | |
485 ;; "Ghost" instructions occupy no space. | |
486 (eq_attr "type" "ghost") | |
487 (const_int 0) | |
488 | |
489 (eq_attr "got" "load") | |
490 (if_then_else (ne (symbol_ref "TARGET_MIPS16") (const_int 0)) | |
491 (const_int 8) | |
492 (const_int 4)) | |
493 (eq_attr "got" "xgot_high") | |
494 (const_int 8) | |
495 | |
496 ;; In general, constant-pool loads are extended instructions. | |
497 (eq_attr "move_type" "loadpool") | |
498 (const_int 8) | |
499 | |
500 ;; LUI_MOVFs are decomposed into two separate instructions. | |
501 (eq_attr "move_type" "lui_movf") | |
502 (const_int 8) | |
503 | |
504 ;; SHIFT_SHIFTs are decomposed into two separate instructions. | |
505 ;; They are extended instructions on MIPS16 targets. | |
506 (eq_attr "move_type" "shift_shift") | |
507 (if_then_else (ne (symbol_ref "TARGET_MIPS16") (const_int 0)) | |
508 (const_int 16) | |
509 (const_int 8)) | |
510 | |
511 ;; Check for doubleword moves that are decomposed into two | |
512 ;; instructions. | |
513 (and (eq_attr "move_type" "mtc,mfc,mthilo,mfhilo,move") | |
514 (eq_attr "dword_mode" "yes")) | |
515 (const_int 8) | |
516 | |
517 ;; Doubleword CONST{,N} moves are split into two word | |
518 ;; CONST{,N} moves. | |
519 (and (eq_attr "move_type" "const,constN") | |
520 (eq_attr "dword_mode" "yes")) | |
521 (symbol_ref "mips_split_const_insns (operands[1]) * 4") | |
522 | |
523 ;; Otherwise, constants, loads and stores are handled by external | |
524 ;; routines. | |
525 (eq_attr "move_type" "const,constN") | |
526 (symbol_ref "mips_const_insns (operands[1]) * 4") | |
527 (eq_attr "move_type" "load,fpload") | |
528 (symbol_ref "mips_load_store_insns (operands[1], insn) * 4") | |
529 (eq_attr "move_type" "store,fpstore") | |
530 (symbol_ref "mips_load_store_insns (operands[0], insn) * 4") | |
531 | |
532 ;; In the worst case, a call macro will take 8 instructions: | |
533 ;; | |
534 ;; lui $25,%call_hi(FOO) | |
535 ;; addu $25,$25,$28 | |
536 ;; lw $25,%call_lo(FOO)($25) | |
537 ;; nop | |
538 ;; jalr $25 | |
539 ;; nop | |
540 ;; lw $gp,X($sp) | |
541 ;; nop | |
542 (eq_attr "jal_macro" "yes") | |
543 (const_int 32) | |
544 | |
545 ;; Various VR4120 errata require a nop to be inserted after a macc | |
546 ;; instruction. The assembler does this for us, so account for | |
547 ;; the worst-case length here. | |
548 (and (eq_attr "type" "imadd") | |
549 (ne (symbol_ref "TARGET_FIX_VR4120") (const_int 0))) | |
550 (const_int 8) | |
551 | |
552 ;; VR4120 errata MD(4): if there are consecutive dmult instructions, | |
553 ;; the result of the second one is missed. The assembler should work | |
554 ;; around this by inserting a nop after the first dmult. | |
555 (and (eq_attr "type" "imul,imul3") | |
556 (and (eq_attr "mode" "DI") | |
557 (ne (symbol_ref "TARGET_FIX_VR4120") (const_int 0)))) | |
558 (const_int 8) | |
559 | |
560 (eq_attr "type" "idiv,idiv3") | |
561 (symbol_ref "mips_idiv_insns () * 4") | |
562 ] (const_int 4))) | |
563 | |
564 ;; Attribute describing the processor. This attribute must match exactly | |
565 ;; with the processor_type enumeration in mips.h. | |
566 (define_attr "cpu" | |
567 "r3000,4kc,4kp,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,74kc,74kf2_1,74kf1_1,74kf3_2,loongson_2e,loongson_2f,m4k,octeon,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,r10000,sb1,sb1a,sr71000,xlr" | |
568 (const (symbol_ref "mips_tune"))) | |
569 | |
570 ;; The type of hardware hazard associated with this instruction. | |
571 ;; DELAY means that the next instruction cannot read the result | |
572 ;; of this one. HILO means that the next two instructions cannot | |
573 ;; write to HI or LO. | |
574 (define_attr "hazard" "none,delay,hilo" | |
575 (cond [(and (eq_attr "type" "load,fpload,fpidxload") | |
576 (ne (symbol_ref "ISA_HAS_LOAD_DELAY") (const_int 0))) | |
577 (const_string "delay") | |
578 | |
579 (and (eq_attr "type" "mfc,mtc") | |
580 (ne (symbol_ref "ISA_HAS_XFER_DELAY") (const_int 0))) | |
581 (const_string "delay") | |
582 | |
583 (and (eq_attr "type" "fcmp") | |
584 (ne (symbol_ref "ISA_HAS_FCMP_DELAY") (const_int 0))) | |
585 (const_string "delay") | |
586 | |
587 ;; The r4000 multiplication patterns include an mflo instruction. | |
588 (and (eq_attr "type" "imul") | |
589 (ne (symbol_ref "TARGET_FIX_R4000") (const_int 0))) | |
590 (const_string "hilo") | |
591 | |
592 (and (eq_attr "type" "mfhilo") | |
593 (eq (symbol_ref "ISA_HAS_HILO_INTERLOCKS") (const_int 0))) | |
594 (const_string "hilo")] | |
595 (const_string "none"))) | |
596 | |
597 ;; Is it a single instruction? | |
598 (define_attr "single_insn" "no,yes" | |
599 (symbol_ref "get_attr_length (insn) == (TARGET_MIPS16 ? 2 : 4)")) | |
600 | |
601 ;; Can the instruction be put into a delay slot? | |
602 (define_attr "can_delay" "no,yes" | |
603 (if_then_else (and (eq_attr "type" "!branch,call,jump") | |
604 (and (eq_attr "hazard" "none") | |
605 (eq_attr "single_insn" "yes"))) | |
606 (const_string "yes") | |
607 (const_string "no"))) | |
608 | |
609 ;; Attribute defining whether or not we can use the branch-likely | |
610 ;; instructions. | |
611 (define_attr "branch_likely" "no,yes" | |
612 (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0)) | |
613 (const_string "yes") | |
614 (const_string "no"))) | |
615 | |
616 ;; True if an instruction might assign to hi or lo when reloaded. | |
617 ;; This is used by the TUNE_MACC_CHAINS code. | |
618 (define_attr "may_clobber_hilo" "no,yes" | |
619 (if_then_else (eq_attr "type" "imul,imul3,imadd,idiv,mthilo") | |
620 (const_string "yes") | |
621 (const_string "no"))) | |
622 | |
623 ;; Describe a user's asm statement. | |
624 (define_asm_attributes | |
625 [(set_attr "type" "multi") | |
626 (set_attr "can_delay" "no")]) | |
627 | |
628 ;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated | |
629 ;; from the same template. | |
630 (define_mode_iterator GPR [SI (DI "TARGET_64BIT")]) | |
631 | |
632 ;; A copy of GPR that can be used when a pattern has two independent | |
633 ;; modes. | |
634 (define_mode_iterator GPR2 [SI (DI "TARGET_64BIT")]) | |
635 | |
636 ;; This mode iterator allows :HILO to be used as the mode of the | |
637 ;; concatenated HI and LO registers. | |
638 (define_mode_iterator HILO [(DI "!TARGET_64BIT") (TI "TARGET_64BIT")]) | |
639 | |
640 ;; This mode iterator allows :P to be used for patterns that operate on | |
641 ;; pointer-sized quantities. Exactly one of the two alternatives will match. | |
642 (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) | |
643 | |
644 ;; This mode iterator allows :MOVECC to be used anywhere that a | |
645 ;; conditional-move-type condition is needed. | |
646 (define_mode_iterator MOVECC [SI (DI "TARGET_64BIT") | |
647 (CC "TARGET_HARD_FLOAT && !TARGET_LOONGSON_2EF")]) | |
648 | |
649 ;; 32-bit integer moves for which we provide move patterns. | |
650 (define_mode_iterator IMOVE32 | |
651 [SI | |
652 (V2HI "TARGET_DSP") | |
653 (V4QI "TARGET_DSP") | |
654 (V2HQ "TARGET_DSP") | |
655 (V2UHQ "TARGET_DSP") | |
656 (V2HA "TARGET_DSP") | |
657 (V2UHA "TARGET_DSP") | |
658 (V4QQ "TARGET_DSP") | |
659 (V4UQQ "TARGET_DSP")]) | |
660 | |
661 ;; 64-bit modes for which we provide move patterns. | |
662 (define_mode_iterator MOVE64 | |
663 [DI DF | |
664 (V2SF "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT") | |
665 (V2SI "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS") | |
666 (V4HI "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS") | |
667 (V8QI "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS")]) | |
668 | |
669 ;; 128-bit modes for which we provide move patterns on 64-bit targets. | |
670 (define_mode_iterator MOVE128 [TI TF]) | |
671 | |
672 ;; This mode iterator allows the QI and HI extension patterns to be | |
673 ;; defined from the same template. | |
674 (define_mode_iterator SHORT [QI HI]) | |
675 | |
676 ;; Likewise the 64-bit truncate-and-shift patterns. | |
677 (define_mode_iterator SUBDI [QI HI SI]) | |
678 | |
679 ;; This mode iterator allows :ANYF to be used wherever a scalar or vector | |
680 ;; floating-point mode is allowed. | |
681 (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT") | |
682 (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT") | |
683 (V2SF "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT")]) | |
684 | |
685 ;; Like ANYF, but only applies to scalar modes. | |
686 (define_mode_iterator SCALARF [(SF "TARGET_HARD_FLOAT") | |
687 (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT")]) | |
688 | |
689 ;; A floating-point mode for which moves involving FPRs may need to be split. | |
690 (define_mode_iterator SPLITF | |
691 [(DF "!TARGET_64BIT && TARGET_DOUBLE_FLOAT") | |
692 (DI "!TARGET_64BIT && TARGET_DOUBLE_FLOAT") | |
693 (V2SF "!TARGET_64BIT && TARGET_PAIRED_SINGLE_FLOAT") | |
694 (V2SI "!TARGET_64BIT && TARGET_LOONGSON_VECTORS") | |
695 (V4HI "!TARGET_64BIT && TARGET_LOONGSON_VECTORS") | |
696 (V8QI "!TARGET_64BIT && TARGET_LOONGSON_VECTORS") | |
697 (TF "TARGET_64BIT && TARGET_FLOAT64")]) | |
698 | |
699 ;; In GPR templates, a string like "<d>subu" will expand to "subu" in the | |
700 ;; 32-bit version and "dsubu" in the 64-bit version. | |
701 (define_mode_attr d [(SI "") (DI "d") | |
702 (QQ "") (HQ "") (SQ "") (DQ "d") | |
703 (UQQ "") (UHQ "") (USQ "") (UDQ "d") | |
704 (HA "") (SA "") (DA "d") | |
705 (UHA "") (USA "") (UDA "d")]) | |
706 | |
707 ;; Same as d but upper-case. | |
708 (define_mode_attr D [(SI "") (DI "D") | |
709 (QQ "") (HQ "") (SQ "") (DQ "D") | |
710 (UQQ "") (UHQ "") (USQ "") (UDQ "D") | |
711 (HA "") (SA "") (DA "D") | |
712 (UHA "") (USA "") (UDA "D")]) | |
713 | |
714 ;; This attribute gives the length suffix for a sign- or zero-extension | |
715 ;; instruction. | |
716 (define_mode_attr size [(QI "b") (HI "h")]) | |
717 | |
718 ;; This attributes gives the mode mask of a SHORT. | |
719 (define_mode_attr mask [(QI "0x00ff") (HI "0xffff")]) | |
720 | |
721 ;; Mode attributes for GPR loads and stores. | |
722 (define_mode_attr load [(SI "lw") (DI "ld")]) | |
723 (define_mode_attr store [(SI "sw") (DI "sd")]) | |
724 | |
725 ;; Similarly for MIPS IV indexed FPR loads and stores. | |
726 (define_mode_attr loadx [(SF "lwxc1") (DF "ldxc1") (V2SF "ldxc1")]) | |
727 (define_mode_attr storex [(SF "swxc1") (DF "sdxc1") (V2SF "sdxc1")]) | |
728 | |
729 ;; The unextended ranges of the MIPS16 addiu and daddiu instructions | |
730 ;; are different. Some forms of unextended addiu have an 8-bit immediate | |
731 ;; field but the equivalent daddiu has only a 5-bit field. | |
732 (define_mode_attr si8_di5 [(SI "8") (DI "5")]) | |
733 | |
734 ;; This attribute gives the best constraint to use for registers of | |
735 ;; a given mode. | |
736 (define_mode_attr reg [(SI "d") (DI "d") (CC "z")]) | |
737 | |
738 ;; This attribute gives the format suffix for floating-point operations. | |
739 (define_mode_attr fmt [(SF "s") (DF "d") (V2SF "ps")]) | |
740 | |
741 ;; This attribute gives the upper-case mode name for one unit of a | |
742 ;; floating-point mode. | |
743 (define_mode_attr UNITMODE [(SF "SF") (DF "DF") (V2SF "SF")]) | |
744 | |
745 ;; This attribute gives the integer mode that has the same size as a | |
746 ;; fixed-point mode. | |
747 (define_mode_attr IMODE [(QQ "QI") (HQ "HI") (SQ "SI") (DQ "DI") | |
748 (UQQ "QI") (UHQ "HI") (USQ "SI") (UDQ "DI") | |
749 (HA "HI") (SA "SI") (DA "DI") | |
750 (UHA "HI") (USA "SI") (UDA "DI") | |
751 (V4UQQ "SI") (V2UHQ "SI") (V2UHA "SI") | |
752 (V2HQ "SI") (V2HA "SI")]) | |
753 | |
754 ;; This attribute gives the integer mode that has half the size of | |
755 ;; the controlling mode. | |
756 (define_mode_attr HALFMODE [(DF "SI") (DI "SI") (V2SF "SI") | |
757 (V2SI "SI") (V4HI "SI") (V8QI "SI") | |
758 (TF "DI")]) | |
759 | |
760 ;; This attribute works around the early SB-1 rev2 core "F2" erratum: | |
761 ;; | |
762 ;; In certain cases, div.s and div.ps may have a rounding error | |
763 ;; and/or wrong inexact flag. | |
764 ;; | |
765 ;; Therefore, we only allow div.s if not working around SB-1 rev2 | |
766 ;; errata or if a slight loss of precision is OK. | |
767 (define_mode_attr divide_condition | |
768 [DF (SF "!TARGET_FIX_SB1 || flag_unsafe_math_optimizations") | |
769 (V2SF "TARGET_SB1 && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)")]) | |
770 | |
771 ;; This attribute gives the conditions under which SQRT.fmt instructions | |
772 ;; can be used. | |
773 (define_mode_attr sqrt_condition | |
774 [(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")]) | |
775 | |
776 ;; This attribute gives the conditions under which RECIP.fmt and RSQRT.fmt | |
777 ;; instructions can be used. The MIPS32 and MIPS64 ISAs say that RECIP.D | |
778 ;; and RSQRT.D are unpredictable when doubles are stored in pairs of FPRs, | |
779 ;; so for safety's sake, we apply this restriction to all targets. | |
780 (define_mode_attr recip_condition | |
781 [(SF "ISA_HAS_FP4") | |
782 (DF "ISA_HAS_FP4 && TARGET_FLOAT64") | |
783 (V2SF "TARGET_SB1")]) | |
784 | |
785 ;; This code iterator allows all branch instructions to be generated from | |
786 ;; a single define_expand template. | |
787 (define_code_iterator any_cond [unordered ordered unlt unge uneq ltgt unle ungt | |
788 eq ne gt ge lt le gtu geu ltu leu]) | |
789 | |
790 ;; This code iterator allows signed and unsigned widening multiplications | |
791 ;; to use the same template. | |
792 (define_code_iterator any_extend [sign_extend zero_extend]) | |
793 | |
794 ;; This code iterator allows the two right shift instructions to be | |
795 ;; generated from the same template. | |
796 (define_code_iterator any_shiftrt [ashiftrt lshiftrt]) | |
797 | |
798 ;; This code iterator allows the three shift instructions to be generated | |
799 ;; from the same template. | |
800 (define_code_iterator any_shift [ashift ashiftrt lshiftrt]) | |
801 | |
802 ;; This code iterator allows unsigned and signed division to be generated | |
803 ;; from the same template. | |
804 (define_code_iterator any_div [div udiv]) | |
805 | |
806 ;; This code iterator allows unsigned and signed modulus to be generated | |
807 ;; from the same template. | |
808 (define_code_iterator any_mod [mod umod]) | |
809 | |
810 ;; This code iterator allows all native floating-point comparisons to be | |
811 ;; generated from the same template. | |
812 (define_code_iterator fcond [unordered uneq unlt unle eq lt le]) | |
813 | |
814 ;; This code iterator is used for comparisons that can be implemented | |
815 ;; by swapping the operands. | |
816 (define_code_iterator swapped_fcond [ge gt unge ungt]) | |
817 | |
818 ;; Equality operators. | |
819 (define_code_iterator equality_op [eq ne]) | |
820 | |
821 ;; These code iterators allow the signed and unsigned scc operations to use | |
822 ;; the same template. | |
823 (define_code_iterator any_gt [gt gtu]) | |
824 (define_code_iterator any_ge [ge geu]) | |
825 (define_code_iterator any_lt [lt ltu]) | |
826 (define_code_iterator any_le [le leu]) | |
827 | |
828 ;; <u> expands to an empty string when doing a signed operation and | |
829 ;; "u" when doing an unsigned operation. | |
830 (define_code_attr u [(sign_extend "") (zero_extend "u") | |
831 (div "") (udiv "u") | |
832 (mod "") (umod "u") | |
833 (gt "") (gtu "u") | |
834 (ge "") (geu "u") | |
835 (lt "") (ltu "u") | |
836 (le "") (leu "u")]) | |
837 | |
838 ;; <su> is like <u>, but the signed form expands to "s" rather than "". | |
839 (define_code_attr su [(sign_extend "s") (zero_extend "u")]) | |
840 | |
841 ;; <optab> expands to the name of the optab for a particular code. | |
842 (define_code_attr optab [(ashift "ashl") | |
843 (ashiftrt "ashr") | |
844 (lshiftrt "lshr") | |
845 (ior "ior") | |
846 (xor "xor") | |
847 (and "and") | |
848 (plus "add") | |
849 (minus "sub")]) | |
850 | |
851 ;; <insn> expands to the name of the insn that implements a particular code. | |
852 (define_code_attr insn [(ashift "sll") | |
853 (ashiftrt "sra") | |
854 (lshiftrt "srl") | |
855 (ior "or") | |
856 (xor "xor") | |
857 (and "and") | |
858 (plus "addu") | |
859 (minus "subu")]) | |
860 | |
861 ;; <immediate_insn> expands to the name of the insn that implements | |
862 ;; a particular code to operate on immediate values. | |
863 (define_code_attr immediate_insn [(ior "ori") | |
864 (xor "xori") | |
865 (and "andi")]) | |
866 | |
867 ;; <fcond> is the c.cond.fmt condition associated with a particular code. | |
868 (define_code_attr fcond [(unordered "un") | |
869 (uneq "ueq") | |
870 (unlt "ult") | |
871 (unle "ule") | |
872 (eq "eq") | |
873 (lt "lt") | |
874 (le "le")]) | |
875 | |
876 ;; Similar, but for swapped conditions. | |
877 (define_code_attr swapped_fcond [(ge "le") | |
878 (gt "lt") | |
879 (unge "ule") | |
880 (ungt "ult")]) | |
881 | |
882 ;; The value of the bit when the branch is taken for branch_bit patterns. | |
883 ;; Comparison is always against zero so this depends on the operator. | |
884 (define_code_attr bbv [(eq "0") (ne "1")]) | |
885 | |
886 ;; This is the inverse value of bbv. | |
887 (define_code_attr bbinv [(eq "1") (ne "0")]) | |
888 | |
889 ;; ......................... | |
890 ;; | |
891 ;; Branch, call and jump delay slots | |
892 ;; | |
893 ;; ......................... | |
894 | |
895 (define_delay (and (eq_attr "type" "branch") | |
896 (eq (symbol_ref "TARGET_MIPS16") (const_int 0)) | |
897 (eq_attr "branch_likely" "yes")) | |
898 [(eq_attr "can_delay" "yes") | |
899 (nil) | |
900 (eq_attr "can_delay" "yes")]) | |
901 | |
902 ;; Branches that don't have likely variants do not annul on false. | |
903 (define_delay (and (eq_attr "type" "branch") | |
904 (eq (symbol_ref "TARGET_MIPS16") (const_int 0)) | |
905 (eq_attr "branch_likely" "no")) | |
906 [(eq_attr "can_delay" "yes") | |
907 (nil) | |
908 (nil)]) | |
909 | |
910 (define_delay (eq_attr "type" "jump") | |
911 [(eq_attr "can_delay" "yes") | |
912 (nil) | |
913 (nil)]) | |
914 | |
915 (define_delay (and (eq_attr "type" "call") | |
916 (eq_attr "jal_macro" "no")) | |
917 [(eq_attr "can_delay" "yes") | |
918 (nil) | |
919 (nil)]) | |
920 | |
921 ;; Pipeline descriptions. | |
922 ;; | |
923 ;; generic.md provides a fallback for processors without a specific | |
924 ;; pipeline description. It is derived from the old define_function_unit | |
925 ;; version and uses the "alu" and "imuldiv" units declared below. | |
926 ;; | |
927 ;; Some of the processor-specific files are also derived from old | |
928 ;; define_function_unit descriptions and simply override the parts of | |
929 ;; generic.md that don't apply. The other processor-specific files | |
930 ;; are self-contained. | |
931 (define_automaton "alu,imuldiv") | |
932 | |
933 (define_cpu_unit "alu" "alu") | |
934 (define_cpu_unit "imuldiv" "imuldiv") | |
935 | |
936 ;; Ghost instructions produce no real code and introduce no hazards. | |
937 ;; They exist purely to express an effect on dataflow. | |
938 (define_insn_reservation "ghost" 0 | |
939 (eq_attr "type" "ghost") | |
940 "nothing") | |
941 | |
942 (include "4k.md") | |
943 (include "5k.md") | |
944 (include "20kc.md") | |
945 (include "24k.md") | |
946 (include "74k.md") | |
947 (include "3000.md") | |
948 (include "4000.md") | |
949 (include "4100.md") | |
950 (include "4130.md") | |
951 (include "4300.md") | |
952 (include "4600.md") | |
953 (include "5000.md") | |
954 (include "5400.md") | |
955 (include "5500.md") | |
956 (include "6000.md") | |
957 (include "7000.md") | |
958 (include "9000.md") | |
959 (include "10000.md") | |
960 (include "loongson2ef.md") | |
961 (include "octeon.md") | |
962 (include "sb1.md") | |
963 (include "sr71k.md") | |
964 (include "xlr.md") | |
965 (include "generic.md") | |
966 | |
967 ;; | |
968 ;; .................... | |
969 ;; | |
970 ;; CONDITIONAL TRAPS | |
971 ;; | |
972 ;; .................... | |
973 ;; | |
974 | |
975 (define_insn "trap" | |
976 [(trap_if (const_int 1) (const_int 0))] | |
977 "" | |
978 { | |
979 if (ISA_HAS_COND_TRAP) | |
980 return "teq\t$0,$0"; | |
981 else if (TARGET_MIPS16) | |
982 return "break 0"; | |
983 else | |
984 return "break"; | |
985 } | |
986 [(set_attr "type" "trap")]) | |
987 | |
988 (define_expand "conditional_trap" | |
989 [(trap_if (match_operator 0 "comparison_operator" | |
990 [(match_dup 2) (match_dup 3)]) | |
991 (match_operand 1 "const_int_operand"))] | |
992 "ISA_HAS_COND_TRAP" | |
993 { | |
994 if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT | |
995 && operands[1] == const0_rtx) | |
996 { | |
997 mips_expand_conditional_trap (GET_CODE (operands[0])); | |
998 DONE; | |
999 } | |
1000 FAIL; | |
1001 }) | |
1002 | |
1003 (define_insn "*conditional_trap<mode>" | |
1004 [(trap_if (match_operator:GPR 0 "trap_comparison_operator" | |
1005 [(match_operand:GPR 1 "reg_or_0_operand" "dJ") | |
1006 (match_operand:GPR 2 "arith_operand" "dI")]) | |
1007 (const_int 0))] | |
1008 "ISA_HAS_COND_TRAP" | |
1009 "t%C0\t%z1,%2" | |
1010 [(set_attr "type" "trap")]) | |
1011 | |
1012 ;; | |
1013 ;; .................... | |
1014 ;; | |
1015 ;; ADDITION | |
1016 ;; | |
1017 ;; .................... | |
1018 ;; | |
1019 | |
1020 (define_insn "add<mode>3" | |
1021 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
1022 (plus:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
1023 (match_operand:ANYF 2 "register_operand" "f")))] | |
1024 "" | |
1025 "add.<fmt>\t%0,%1,%2" | |
1026 [(set_attr "type" "fadd") | |
1027 (set_attr "mode" "<UNITMODE>")]) | |
1028 | |
1029 (define_expand "add<mode>3" | |
1030 [(set (match_operand:GPR 0 "register_operand") | |
1031 (plus:GPR (match_operand:GPR 1 "register_operand") | |
1032 (match_operand:GPR 2 "arith_operand")))] | |
1033 "") | |
1034 | |
1035 (define_insn "*add<mode>3" | |
1036 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
1037 (plus:GPR (match_operand:GPR 1 "register_operand" "d,d") | |
1038 (match_operand:GPR 2 "arith_operand" "d,Q")))] | |
1039 "!TARGET_MIPS16" | |
1040 "@ | |
1041 <d>addu\t%0,%1,%2 | |
1042 <d>addiu\t%0,%1,%2" | |
1043 [(set_attr "type" "arith") | |
1044 (set_attr "mode" "<MODE>")]) | |
1045 | |
1046 (define_insn "*add<mode>3_mips16" | |
1047 [(set (match_operand:GPR 0 "register_operand" "=ks,d,d,d,d") | |
1048 (plus:GPR (match_operand:GPR 1 "register_operand" "ks,ks,0,d,d") | |
1049 (match_operand:GPR 2 "arith_operand" "Q,Q,Q,O,d")))] | |
1050 "TARGET_MIPS16" | |
1051 "@ | |
1052 <d>addiu\t%0,%2 | |
1053 <d>addiu\t%0,%1,%2 | |
1054 <d>addiu\t%0,%2 | |
1055 <d>addiu\t%0,%1,%2 | |
1056 <d>addu\t%0,%1,%2" | |
1057 [(set_attr "type" "arith") | |
1058 (set_attr "mode" "<MODE>") | |
1059 (set_attr_alternative "length" | |
1060 [(if_then_else (match_operand 2 "m16_simm8_8") | |
1061 (const_int 4) | |
1062 (const_int 8)) | |
1063 (if_then_else (match_operand 2 "m16_uimm<si8_di5>_4") | |
1064 (const_int 4) | |
1065 (const_int 8)) | |
1066 (if_then_else (match_operand 2 "m16_simm<si8_di5>_1") | |
1067 (const_int 4) | |
1068 (const_int 8)) | |
1069 (if_then_else (match_operand 2 "m16_simm4_1") | |
1070 (const_int 4) | |
1071 (const_int 8)) | |
1072 (const_int 4)])]) | |
1073 | |
1074 ;; On the mips16, we can sometimes split an add of a constant which is | |
1075 ;; a 4 byte instruction into two adds which are both 2 byte | |
1076 ;; instructions. There are two cases: one where we are adding a | |
1077 ;; constant plus a register to another register, and one where we are | |
1078 ;; simply adding a constant to a register. | |
1079 | |
1080 (define_split | |
1081 [(set (match_operand:SI 0 "d_operand") | |
1082 (plus:SI (match_dup 0) | |
1083 (match_operand:SI 1 "const_int_operand")))] | |
1084 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE | |
1085 && ((INTVAL (operands[1]) > 0x7f | |
1086 && INTVAL (operands[1]) <= 0x7f + 0x7f) | |
1087 || (INTVAL (operands[1]) < - 0x80 | |
1088 && INTVAL (operands[1]) >= - 0x80 - 0x80))" | |
1089 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) | |
1090 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] | |
1091 { | |
1092 HOST_WIDE_INT val = INTVAL (operands[1]); | |
1093 | |
1094 if (val >= 0) | |
1095 { | |
1096 operands[1] = GEN_INT (0x7f); | |
1097 operands[2] = GEN_INT (val - 0x7f); | |
1098 } | |
1099 else | |
1100 { | |
1101 operands[1] = GEN_INT (- 0x80); | |
1102 operands[2] = GEN_INT (val + 0x80); | |
1103 } | |
1104 }) | |
1105 | |
1106 (define_split | |
1107 [(set (match_operand:SI 0 "d_operand") | |
1108 (plus:SI (match_operand:SI 1 "d_operand") | |
1109 (match_operand:SI 2 "const_int_operand")))] | |
1110 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE | |
1111 && REGNO (operands[0]) != REGNO (operands[1]) | |
1112 && ((INTVAL (operands[2]) > 0x7 | |
1113 && INTVAL (operands[2]) <= 0x7 + 0x7f) | |
1114 || (INTVAL (operands[2]) < - 0x8 | |
1115 && INTVAL (operands[2]) >= - 0x8 - 0x80))" | |
1116 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) | |
1117 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] | |
1118 { | |
1119 HOST_WIDE_INT val = INTVAL (operands[2]); | |
1120 | |
1121 if (val >= 0) | |
1122 { | |
1123 operands[2] = GEN_INT (0x7); | |
1124 operands[3] = GEN_INT (val - 0x7); | |
1125 } | |
1126 else | |
1127 { | |
1128 operands[2] = GEN_INT (- 0x8); | |
1129 operands[3] = GEN_INT (val + 0x8); | |
1130 } | |
1131 }) | |
1132 | |
1133 (define_split | |
1134 [(set (match_operand:DI 0 "d_operand") | |
1135 (plus:DI (match_dup 0) | |
1136 (match_operand:DI 1 "const_int_operand")))] | |
1137 "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE | |
1138 && ((INTVAL (operands[1]) > 0xf | |
1139 && INTVAL (operands[1]) <= 0xf + 0xf) | |
1140 || (INTVAL (operands[1]) < - 0x10 | |
1141 && INTVAL (operands[1]) >= - 0x10 - 0x10))" | |
1142 [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) | |
1143 (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))] | |
1144 { | |
1145 HOST_WIDE_INT val = INTVAL (operands[1]); | |
1146 | |
1147 if (val >= 0) | |
1148 { | |
1149 operands[1] = GEN_INT (0xf); | |
1150 operands[2] = GEN_INT (val - 0xf); | |
1151 } | |
1152 else | |
1153 { | |
1154 operands[1] = GEN_INT (- 0x10); | |
1155 operands[2] = GEN_INT (val + 0x10); | |
1156 } | |
1157 }) | |
1158 | |
1159 (define_split | |
1160 [(set (match_operand:DI 0 "d_operand") | |
1161 (plus:DI (match_operand:DI 1 "d_operand") | |
1162 (match_operand:DI 2 "const_int_operand")))] | |
1163 "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE | |
1164 && REGNO (operands[0]) != REGNO (operands[1]) | |
1165 && ((INTVAL (operands[2]) > 0x7 | |
1166 && INTVAL (operands[2]) <= 0x7 + 0xf) | |
1167 || (INTVAL (operands[2]) < - 0x8 | |
1168 && INTVAL (operands[2]) >= - 0x8 - 0x10))" | |
1169 [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) | |
1170 (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] | |
1171 { | |
1172 HOST_WIDE_INT val = INTVAL (operands[2]); | |
1173 | |
1174 if (val >= 0) | |
1175 { | |
1176 operands[2] = GEN_INT (0x7); | |
1177 operands[3] = GEN_INT (val - 0x7); | |
1178 } | |
1179 else | |
1180 { | |
1181 operands[2] = GEN_INT (- 0x8); | |
1182 operands[3] = GEN_INT (val + 0x8); | |
1183 } | |
1184 }) | |
1185 | |
1186 (define_insn "*addsi3_extended" | |
1187 [(set (match_operand:DI 0 "register_operand" "=d,d") | |
1188 (sign_extend:DI | |
1189 (plus:SI (match_operand:SI 1 "register_operand" "d,d") | |
1190 (match_operand:SI 2 "arith_operand" "d,Q"))))] | |
1191 "TARGET_64BIT && !TARGET_MIPS16" | |
1192 "@ | |
1193 addu\t%0,%1,%2 | |
1194 addiu\t%0,%1,%2" | |
1195 [(set_attr "type" "arith") | |
1196 (set_attr "mode" "SI")]) | |
1197 | |
1198 ;; Split this insn so that the addiu splitters can have a crack at it. | |
1199 ;; Use a conservative length estimate until the split. | |
1200 (define_insn_and_split "*addsi3_extended_mips16" | |
1201 [(set (match_operand:DI 0 "register_operand" "=d,d,d") | |
1202 (sign_extend:DI | |
1203 (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") | |
1204 (match_operand:SI 2 "arith_operand" "Q,O,d"))))] | |
1205 "TARGET_64BIT && TARGET_MIPS16" | |
1206 "#" | |
1207 "&& reload_completed" | |
1208 [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))] | |
1209 { operands[3] = gen_lowpart (SImode, operands[0]); } | |
1210 [(set_attr "type" "arith") | |
1211 (set_attr "mode" "SI") | |
1212 (set_attr "extended_mips16" "yes")]) | |
1213 | |
1214 ;; Combiner patterns for unsigned byte-add. | |
1215 | |
1216 (define_insn "*baddu_si_eb" | |
1217 [(set (match_operand:SI 0 "register_operand" "=d") | |
1218 (zero_extend:SI | |
1219 (subreg:QI | |
1220 (plus:SI (match_operand:SI 1 "register_operand" "d") | |
1221 (match_operand:SI 2 "register_operand" "d")) 3)))] | |
1222 "ISA_HAS_BADDU && BYTES_BIG_ENDIAN" | |
1223 "baddu\\t%0,%1,%2" | |
1224 [(set_attr "type" "arith")]) | |
1225 | |
1226 (define_insn "*baddu_si_el" | |
1227 [(set (match_operand:SI 0 "register_operand" "=d") | |
1228 (zero_extend:SI | |
1229 (subreg:QI | |
1230 (plus:SI (match_operand:SI 1 "register_operand" "d") | |
1231 (match_operand:SI 2 "register_operand" "d")) 0)))] | |
1232 "ISA_HAS_BADDU && !BYTES_BIG_ENDIAN" | |
1233 "baddu\\t%0,%1,%2" | |
1234 [(set_attr "type" "arith")]) | |
1235 | |
1236 (define_insn "*baddu_di<mode>" | |
1237 [(set (match_operand:GPR 0 "register_operand" "=d") | |
1238 (zero_extend:GPR | |
1239 (truncate:QI | |
1240 (plus:DI (match_operand:DI 1 "register_operand" "d") | |
1241 (match_operand:DI 2 "register_operand" "d")))))] | |
1242 "ISA_HAS_BADDU && TARGET_64BIT" | |
1243 "baddu\\t%0,%1,%2" | |
1244 [(set_attr "type" "arith")]) | |
1245 | |
1246 ;; | |
1247 ;; .................... | |
1248 ;; | |
1249 ;; SUBTRACTION | |
1250 ;; | |
1251 ;; .................... | |
1252 ;; | |
1253 | |
1254 (define_insn "sub<mode>3" | |
1255 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
1256 (minus:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
1257 (match_operand:ANYF 2 "register_operand" "f")))] | |
1258 "" | |
1259 "sub.<fmt>\t%0,%1,%2" | |
1260 [(set_attr "type" "fadd") | |
1261 (set_attr "mode" "<UNITMODE>")]) | |
1262 | |
1263 (define_insn "sub<mode>3" | |
1264 [(set (match_operand:GPR 0 "register_operand" "=d") | |
1265 (minus:GPR (match_operand:GPR 1 "register_operand" "d") | |
1266 (match_operand:GPR 2 "register_operand" "d")))] | |
1267 "" | |
1268 "<d>subu\t%0,%1,%2" | |
1269 [(set_attr "type" "arith") | |
1270 (set_attr "mode" "<MODE>")]) | |
1271 | |
1272 (define_insn "*subsi3_extended" | |
1273 [(set (match_operand:DI 0 "register_operand" "=d") | |
1274 (sign_extend:DI | |
1275 (minus:SI (match_operand:SI 1 "register_operand" "d") | |
1276 (match_operand:SI 2 "register_operand" "d"))))] | |
1277 "TARGET_64BIT" | |
1278 "subu\t%0,%1,%2" | |
1279 [(set_attr "type" "arith") | |
1280 (set_attr "mode" "DI")]) | |
1281 | |
1282 ;; | |
1283 ;; .................... | |
1284 ;; | |
1285 ;; MULTIPLICATION | |
1286 ;; | |
1287 ;; .................... | |
1288 ;; | |
1289 | |
1290 (define_expand "mul<mode>3" | |
1291 [(set (match_operand:SCALARF 0 "register_operand") | |
1292 (mult:SCALARF (match_operand:SCALARF 1 "register_operand") | |
1293 (match_operand:SCALARF 2 "register_operand")))] | |
1294 "" | |
1295 "") | |
1296 | |
1297 (define_insn "*mul<mode>3" | |
1298 [(set (match_operand:SCALARF 0 "register_operand" "=f") | |
1299 (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f") | |
1300 (match_operand:SCALARF 2 "register_operand" "f")))] | |
1301 "!TARGET_4300_MUL_FIX" | |
1302 "mul.<fmt>\t%0,%1,%2" | |
1303 [(set_attr "type" "fmul") | |
1304 (set_attr "mode" "<MODE>")]) | |
1305 | |
1306 ;; Early VR4300 silicon has a CPU bug where multiplies with certain | |
1307 ;; operands may corrupt immediately following multiplies. This is a | |
1308 ;; simple fix to insert NOPs. | |
1309 | |
1310 (define_insn "*mul<mode>3_r4300" | |
1311 [(set (match_operand:SCALARF 0 "register_operand" "=f") | |
1312 (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f") | |
1313 (match_operand:SCALARF 2 "register_operand" "f")))] | |
1314 "TARGET_4300_MUL_FIX" | |
1315 "mul.<fmt>\t%0,%1,%2\;nop" | |
1316 [(set_attr "type" "fmul") | |
1317 (set_attr "mode" "<MODE>") | |
1318 (set_attr "length" "8")]) | |
1319 | |
1320 (define_insn "mulv2sf3" | |
1321 [(set (match_operand:V2SF 0 "register_operand" "=f") | |
1322 (mult:V2SF (match_operand:V2SF 1 "register_operand" "f") | |
1323 (match_operand:V2SF 2 "register_operand" "f")))] | |
1324 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" | |
1325 "mul.ps\t%0,%1,%2" | |
1326 [(set_attr "type" "fmul") | |
1327 (set_attr "mode" "SF")]) | |
1328 | |
1329 ;; The original R4000 has a cpu bug. If a double-word or a variable | |
1330 ;; shift executes while an integer multiplication is in progress, the | |
1331 ;; shift may give an incorrect result. Avoid this by keeping the mflo | |
1332 ;; with the mult on the R4000. | |
1333 ;; | |
1334 ;; From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0" | |
1335 ;; (also valid for MIPS R4000MC processors): | |
1336 ;; | |
1337 ;; "16. R4000PC, R4000SC: Please refer to errata 28 for an update to | |
1338 ;; this errata description. | |
1339 ;; The following code sequence causes the R4000 to incorrectly | |
1340 ;; execute the Double Shift Right Arithmetic 32 (dsra32) | |
1341 ;; instruction. If the dsra32 instruction is executed during an | |
1342 ;; integer multiply, the dsra32 will only shift by the amount in | |
1343 ;; specified in the instruction rather than the amount plus 32 | |
1344 ;; bits. | |
1345 ;; instruction 1: mult rs,rt integer multiply | |
1346 ;; instruction 2-12: dsra32 rd,rt,rs doubleword shift | |
1347 ;; right arithmetic + 32 | |
1348 ;; Workaround: A dsra32 instruction placed after an integer | |
1349 ;; multiply should not be one of the 11 instructions after the | |
1350 ;; multiply instruction." | |
1351 ;; | |
1352 ;; and: | |
1353 ;; | |
1354 ;; "28. R4000PC, R4000SC: The text from errata 16 should be replaced by | |
1355 ;; the following description. | |
1356 ;; All extended shifts (shift by n+32) and variable shifts (32 and | |
1357 ;; 64-bit versions) may produce incorrect results under the | |
1358 ;; following conditions: | |
1359 ;; 1) An integer multiply is currently executing | |
1360 ;; 2) These types of shift instructions are executed immediately | |
1361 ;; following an integer divide instruction. | |
1362 ;; Workaround: | |
1363 ;; 1) Make sure no integer multiply is running wihen these | |
1364 ;; instruction are executed. If this cannot be predicted at | |
1365 ;; compile time, then insert a "mfhi" to R0 instruction | |
1366 ;; immediately after the integer multiply instruction. This | |
1367 ;; will cause the integer multiply to complete before the shift | |
1368 ;; is executed. | |
1369 ;; 2) Separate integer divide and these two classes of shift | |
1370 ;; instructions by another instruction or a noop." | |
1371 ;; | |
1372 ;; These processors have PRId values of 0x00004220 and 0x00004300, | |
1373 ;; respectively. | |
1374 | |
1375 (define_expand "mul<mode>3" | |
1376 [(set (match_operand:GPR 0 "register_operand") | |
1377 (mult:GPR (match_operand:GPR 1 "register_operand") | |
1378 (match_operand:GPR 2 "register_operand")))] | |
1379 "" | |
1380 { | |
1381 if (TARGET_LOONGSON_2EF) | |
1382 emit_insn (gen_mul<mode>3_mul3_ls2ef (operands[0], operands[1], | |
1383 operands[2])); | |
1384 else if (ISA_HAS_<D>MUL3) | |
1385 emit_insn (gen_mul<mode>3_mul3 (operands[0], operands[1], operands[2])); | |
1386 else if (TARGET_FIX_R4000) | |
1387 emit_insn (gen_mul<mode>3_r4000 (operands[0], operands[1], operands[2])); | |
1388 else | |
1389 emit_insn | |
1390 (gen_mul<mode>3_internal (operands[0], operands[1], operands[2])); | |
1391 DONE; | |
1392 }) | |
1393 | |
1394 (define_insn "mul<mode>3_mul3_ls2ef" | |
1395 [(set (match_operand:GPR 0 "register_operand" "=d") | |
1396 (mult:GPR (match_operand:GPR 1 "register_operand" "d") | |
1397 (match_operand:GPR 2 "register_operand" "d")))] | |
1398 "TARGET_LOONGSON_2EF" | |
1399 "<d>multu.g\t%0,%1,%2" | |
1400 [(set_attr "type" "imul3nc") | |
1401 (set_attr "mode" "<MODE>")]) | |
1402 | |
1403 (define_insn "mul<mode>3_mul3" | |
1404 [(set (match_operand:GPR 0 "register_operand" "=d,l") | |
1405 (mult:GPR (match_operand:GPR 1 "register_operand" "d,d") | |
1406 (match_operand:GPR 2 "register_operand" "d,d"))) | |
1407 (clobber (match_scratch:GPR 3 "=l,X"))] | |
1408 "ISA_HAS_<D>MUL3" | |
1409 { | |
1410 if (which_alternative == 1) | |
1411 return "<d>mult\t%1,%2"; | |
1412 if (<MODE>mode == SImode && TARGET_MIPS3900) | |
1413 return "mult\t%0,%1,%2"; | |
1414 return "<d>mul\t%0,%1,%2"; | |
1415 } | |
1416 [(set_attr "type" "imul3,imul") | |
1417 (set_attr "mode" "<MODE>")]) | |
1418 | |
1419 ;; If a register gets allocated to LO, and we spill to memory, the reload | |
1420 ;; will include a move from LO to a GPR. Merge it into the multiplication | |
1421 ;; if it can set the GPR directly. | |
1422 ;; | |
1423 ;; Operand 0: LO | |
1424 ;; Operand 1: GPR (1st multiplication operand) | |
1425 ;; Operand 2: GPR (2nd multiplication operand) | |
1426 ;; Operand 3: GPR (destination) | |
1427 (define_peephole2 | |
1428 [(parallel | |
1429 [(set (match_operand:SI 0 "lo_operand") | |
1430 (mult:SI (match_operand:SI 1 "d_operand") | |
1431 (match_operand:SI 2 "d_operand"))) | |
1432 (clobber (scratch:SI))]) | |
1433 (set (match_operand:SI 3 "d_operand") | |
1434 (match_dup 0))] | |
1435 "ISA_HAS_MUL3 && peep2_reg_dead_p (2, operands[0])" | |
1436 [(parallel | |
1437 [(set (match_dup 3) | |
1438 (mult:SI (match_dup 1) | |
1439 (match_dup 2))) | |
1440 (clobber (match_dup 0))])]) | |
1441 | |
1442 (define_insn "mul<mode>3_internal" | |
1443 [(set (match_operand:GPR 0 "register_operand" "=l") | |
1444 (mult:GPR (match_operand:GPR 1 "register_operand" "d") | |
1445 (match_operand:GPR 2 "register_operand" "d")))] | |
1446 "!TARGET_FIX_R4000" | |
1447 "<d>mult\t%1,%2" | |
1448 [(set_attr "type" "imul") | |
1449 (set_attr "mode" "<MODE>")]) | |
1450 | |
1451 (define_insn "mul<mode>3_r4000" | |
1452 [(set (match_operand:GPR 0 "register_operand" "=d") | |
1453 (mult:GPR (match_operand:GPR 1 "register_operand" "d") | |
1454 (match_operand:GPR 2 "register_operand" "d"))) | |
1455 (clobber (match_scratch:GPR 3 "=l"))] | |
1456 "TARGET_FIX_R4000" | |
1457 "<d>mult\t%1,%2\;mflo\t%0" | |
1458 [(set_attr "type" "imul") | |
1459 (set_attr "mode" "<MODE>") | |
1460 (set_attr "length" "8")]) | |
1461 | |
1462 ;; On the VR4120 and VR4130, it is better to use "mtlo $0; macc" instead | |
1463 ;; of "mult; mflo". They have the same latency, but the first form gives | |
1464 ;; us an extra cycle to compute the operands. | |
1465 | |
1466 ;; Operand 0: LO | |
1467 ;; Operand 1: GPR (1st multiplication operand) | |
1468 ;; Operand 2: GPR (2nd multiplication operand) | |
1469 ;; Operand 3: GPR (destination) | |
1470 (define_peephole2 | |
1471 [(set (match_operand:SI 0 "lo_operand") | |
1472 (mult:SI (match_operand:SI 1 "d_operand") | |
1473 (match_operand:SI 2 "d_operand"))) | |
1474 (set (match_operand:SI 3 "d_operand") | |
1475 (match_dup 0))] | |
1476 "ISA_HAS_MACC && !ISA_HAS_MUL3" | |
1477 [(set (match_dup 0) | |
1478 (const_int 0)) | |
1479 (parallel | |
1480 [(set (match_dup 0) | |
1481 (plus:SI (mult:SI (match_dup 1) | |
1482 (match_dup 2)) | |
1483 (match_dup 0))) | |
1484 (set (match_dup 3) | |
1485 (plus:SI (mult:SI (match_dup 1) | |
1486 (match_dup 2)) | |
1487 (match_dup 0)))])]) | |
1488 | |
1489 ;; Multiply-accumulate patterns | |
1490 | |
1491 ;; This pattern is first matched by combine, which tries to use the | |
1492 ;; pattern wherever it can. We don't know until later whether it | |
1493 ;; is actually profitable to use MADD over a "MUL; ADDIU" sequence, | |
1494 ;; so we need to keep both options open. | |
1495 ;; | |
1496 ;; The second alternative has a "?" marker because it is generally | |
1497 ;; one instruction more costly than the first alternative. This "?" | |
1498 ;; marker is enough to convey the relative costs to the register | |
1499 ;; allocator. | |
1500 ;; | |
1501 ;; However, reload counts reloads of operands 4 and 5 in the same way as | |
1502 ;; reloads of the other operands, even though operands 4 and 5 need no | |
1503 ;; copy instructions. Reload therefore thinks that the second alternative | |
1504 ;; is two reloads more costly than the first. We add "*?*?" to the first | |
1505 ;; alternative as a counterweight. | |
1506 (define_insn "*mul_acc_si" | |
1507 [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?") | |
1508 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") | |
1509 (match_operand:SI 2 "register_operand" "d,d")) | |
1510 (match_operand:SI 3 "register_operand" "0,d"))) | |
1511 (clobber (match_scratch:SI 4 "=X,l")) | |
1512 (clobber (match_scratch:SI 5 "=X,&d"))] | |
1513 "GENERATE_MADD_MSUB && !TARGET_MIPS16" | |
1514 "@ | |
1515 madd\t%1,%2 | |
1516 #" | |
1517 [(set_attr "type" "imadd") | |
1518 (set_attr "mode" "SI") | |
1519 (set_attr "length" "4,8")]) | |
1520 | |
1521 ;; The same idea applies here. The middle alternative needs one less | |
1522 ;; clobber than the final alternative, so we add "*?" as a counterweight. | |
1523 (define_insn "*mul_acc_si_r3900" | |
1524 [(set (match_operand:SI 0 "register_operand" "=l*?*?,d*?,d?") | |
1525 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") | |
1526 (match_operand:SI 2 "register_operand" "d,d,d")) | |
1527 (match_operand:SI 3 "register_operand" "0,l,d"))) | |
1528 (clobber (match_scratch:SI 4 "=X,3,l")) | |
1529 (clobber (match_scratch:SI 5 "=X,X,&d"))] | |
1530 "TARGET_MIPS3900 && !TARGET_MIPS16" | |
1531 "@ | |
1532 madd\t%1,%2 | |
1533 madd\t%0,%1,%2 | |
1534 #" | |
1535 [(set_attr "type" "imadd") | |
1536 (set_attr "mode" "SI") | |
1537 (set_attr "length" "4,4,8")]) | |
1538 | |
1539 ;; Split *mul_acc_si if both the source and destination accumulator | |
1540 ;; values are GPRs. | |
1541 (define_split | |
1542 [(set (match_operand:SI 0 "d_operand") | |
1543 (plus:SI (mult:SI (match_operand:SI 1 "d_operand") | |
1544 (match_operand:SI 2 "d_operand")) | |
1545 (match_operand:SI 3 "d_operand"))) | |
1546 (clobber (match_operand:SI 4 "lo_operand")) | |
1547 (clobber (match_operand:SI 5 "d_operand"))] | |
1548 "reload_completed" | |
1549 [(parallel [(set (match_dup 5) | |
1550 (mult:SI (match_dup 1) (match_dup 2))) | |
1551 (clobber (match_dup 4))]) | |
1552 (set (match_dup 0) (plus:SI (match_dup 5) (match_dup 3)))] | |
1553 "") | |
1554 | |
1555 (define_insn "*macc" | |
1556 [(set (match_operand:SI 0 "register_operand" "=l,d") | |
1557 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") | |
1558 (match_operand:SI 2 "register_operand" "d,d")) | |
1559 (match_operand:SI 3 "register_operand" "0,l"))) | |
1560 (clobber (match_scratch:SI 4 "=X,3"))] | |
1561 "ISA_HAS_MACC" | |
1562 { | |
1563 if (which_alternative == 1) | |
1564 return "macc\t%0,%1,%2"; | |
1565 else if (TARGET_MIPS5500) | |
1566 return "madd\t%1,%2"; | |
1567 else | |
1568 /* The VR4130 assumes that there is a two-cycle latency between a macc | |
1569 that "writes" to $0 and an instruction that reads from it. We avoid | |
1570 this by assigning to $1 instead. */ | |
1571 return "%[macc\t%@,%1,%2%]"; | |
1572 } | |
1573 [(set_attr "type" "imadd") | |
1574 (set_attr "mode" "SI")]) | |
1575 | |
1576 (define_insn "*msac" | |
1577 [(set (match_operand:SI 0 "register_operand" "=l,d") | |
1578 (minus:SI (match_operand:SI 1 "register_operand" "0,l") | |
1579 (mult:SI (match_operand:SI 2 "register_operand" "d,d") | |
1580 (match_operand:SI 3 "register_operand" "d,d")))) | |
1581 (clobber (match_scratch:SI 4 "=X,1"))] | |
1582 "ISA_HAS_MSAC" | |
1583 { | |
1584 if (which_alternative == 1) | |
1585 return "msac\t%0,%2,%3"; | |
1586 else if (TARGET_MIPS5500) | |
1587 return "msub\t%2,%3"; | |
1588 else | |
1589 return "msac\t$0,%2,%3"; | |
1590 } | |
1591 [(set_attr "type" "imadd") | |
1592 (set_attr "mode" "SI")]) | |
1593 | |
1594 ;; An msac-like instruction implemented using negation and a macc. | |
1595 (define_insn_and_split "*msac_using_macc" | |
1596 [(set (match_operand:SI 0 "register_operand" "=l,d") | |
1597 (minus:SI (match_operand:SI 1 "register_operand" "0,l") | |
1598 (mult:SI (match_operand:SI 2 "register_operand" "d,d") | |
1599 (match_operand:SI 3 "register_operand" "d,d")))) | |
1600 (clobber (match_scratch:SI 4 "=X,1")) | |
1601 (clobber (match_scratch:SI 5 "=d,d"))] | |
1602 "ISA_HAS_MACC && !ISA_HAS_MSAC" | |
1603 "#" | |
1604 "&& reload_completed" | |
1605 [(set (match_dup 5) | |
1606 (neg:SI (match_dup 3))) | |
1607 (parallel | |
1608 [(set (match_dup 0) | |
1609 (plus:SI (mult:SI (match_dup 2) | |
1610 (match_dup 5)) | |
1611 (match_dup 1))) | |
1612 (clobber (match_dup 4))])] | |
1613 "" | |
1614 [(set_attr "type" "imadd") | |
1615 (set_attr "length" "8")]) | |
1616 | |
1617 ;; Patterns generated by the define_peephole2 below. | |
1618 | |
1619 (define_insn "*macc2" | |
1620 [(set (match_operand:SI 0 "register_operand" "=l") | |
1621 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") | |
1622 (match_operand:SI 2 "register_operand" "d")) | |
1623 (match_dup 0))) | |
1624 (set (match_operand:SI 3 "register_operand" "=d") | |
1625 (plus:SI (mult:SI (match_dup 1) | |
1626 (match_dup 2)) | |
1627 (match_dup 0)))] | |
1628 "ISA_HAS_MACC && reload_completed" | |
1629 "macc\t%3,%1,%2" | |
1630 [(set_attr "type" "imadd") | |
1631 (set_attr "mode" "SI")]) | |
1632 | |
1633 (define_insn "*msac2" | |
1634 [(set (match_operand:SI 0 "register_operand" "=l") | |
1635 (minus:SI (match_dup 0) | |
1636 (mult:SI (match_operand:SI 1 "register_operand" "d") | |
1637 (match_operand:SI 2 "register_operand" "d")))) | |
1638 (set (match_operand:SI 3 "register_operand" "=d") | |
1639 (minus:SI (match_dup 0) | |
1640 (mult:SI (match_dup 1) | |
1641 (match_dup 2))))] | |
1642 "ISA_HAS_MSAC && reload_completed" | |
1643 "msac\t%3,%1,%2" | |
1644 [(set_attr "type" "imadd") | |
1645 (set_attr "mode" "SI")]) | |
1646 | |
1647 ;; Convert macc $0,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2> | |
1648 ;; Similarly msac. | |
1649 ;; | |
1650 ;; Operand 0: LO | |
1651 ;; Operand 1: macc/msac | |
1652 ;; Operand 2: GPR (destination) | |
1653 (define_peephole2 | |
1654 [(parallel | |
1655 [(set (match_operand:SI 0 "lo_operand") | |
1656 (match_operand:SI 1 "macc_msac_operand")) | |
1657 (clobber (scratch:SI))]) | |
1658 (set (match_operand:SI 2 "d_operand") | |
1659 (match_dup 0))] | |
1660 "" | |
1661 [(parallel [(set (match_dup 0) | |
1662 (match_dup 1)) | |
1663 (set (match_dup 2) | |
1664 (match_dup 1))])]) | |
1665 | |
1666 ;; When we have a three-address multiplication instruction, it should | |
1667 ;; be faster to do a separate multiply and add, rather than moving | |
1668 ;; something into LO in order to use a macc instruction. | |
1669 ;; | |
1670 ;; This peephole needs a scratch register to cater for the case when one | |
1671 ;; of the multiplication operands is the same as the destination. | |
1672 ;; | |
1673 ;; Operand 0: GPR (scratch) | |
1674 ;; Operand 1: LO | |
1675 ;; Operand 2: GPR (addend) | |
1676 ;; Operand 3: GPR (destination) | |
1677 ;; Operand 4: macc/msac | |
1678 ;; Operand 5: new multiplication | |
1679 ;; Operand 6: new addition/subtraction | |
1680 (define_peephole2 | |
1681 [(match_scratch:SI 0 "d") | |
1682 (set (match_operand:SI 1 "lo_operand") | |
1683 (match_operand:SI 2 "d_operand")) | |
1684 (match_dup 0) | |
1685 (parallel | |
1686 [(set (match_operand:SI 3 "d_operand") | |
1687 (match_operand:SI 4 "macc_msac_operand")) | |
1688 (clobber (match_dup 1))])] | |
1689 "ISA_HAS_MUL3 && peep2_reg_dead_p (2, operands[1])" | |
1690 [(parallel [(set (match_dup 0) | |
1691 (match_dup 5)) | |
1692 (clobber (match_dup 1))]) | |
1693 (set (match_dup 3) | |
1694 (match_dup 6))] | |
1695 { | |
1696 operands[5] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); | |
1697 operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, | |
1698 operands[2], operands[0]); | |
1699 }) | |
1700 | |
1701 ;; Same as above, except LO is the initial target of the macc. | |
1702 ;; | |
1703 ;; Operand 0: GPR (scratch) | |
1704 ;; Operand 1: LO | |
1705 ;; Operand 2: GPR (addend) | |
1706 ;; Operand 3: macc/msac | |
1707 ;; Operand 4: GPR (destination) | |
1708 ;; Operand 5: new multiplication | |
1709 ;; Operand 6: new addition/subtraction | |
1710 (define_peephole2 | |
1711 [(match_scratch:SI 0 "d") | |
1712 (set (match_operand:SI 1 "lo_operand") | |
1713 (match_operand:SI 2 "d_operand")) | |
1714 (match_dup 0) | |
1715 (parallel | |
1716 [(set (match_dup 1) | |
1717 (match_operand:SI 3 "macc_msac_operand")) | |
1718 (clobber (scratch:SI))]) | |
1719 (match_dup 0) | |
1720 (set (match_operand:SI 4 "d_operand") | |
1721 (match_dup 1))] | |
1722 "ISA_HAS_MUL3 && peep2_reg_dead_p (3, operands[1])" | |
1723 [(parallel [(set (match_dup 0) | |
1724 (match_dup 5)) | |
1725 (clobber (match_dup 1))]) | |
1726 (set (match_dup 4) | |
1727 (match_dup 6))] | |
1728 { | |
1729 operands[5] = XEXP (operands[3], GET_CODE (operands[3]) == PLUS ? 0 : 1); | |
1730 operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode, | |
1731 operands[2], operands[0]); | |
1732 }) | |
1733 | |
1734 ;; See the comment above *mul_add_si for details. | |
1735 (define_insn "*mul_sub_si" | |
1736 [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?") | |
1737 (minus:SI (match_operand:SI 1 "register_operand" "0,d") | |
1738 (mult:SI (match_operand:SI 2 "register_operand" "d,d") | |
1739 (match_operand:SI 3 "register_operand" "d,d")))) | |
1740 (clobber (match_scratch:SI 4 "=X,l")) | |
1741 (clobber (match_scratch:SI 5 "=X,&d"))] | |
1742 "GENERATE_MADD_MSUB" | |
1743 "@ | |
1744 msub\t%2,%3 | |
1745 #" | |
1746 [(set_attr "type" "imadd") | |
1747 (set_attr "mode" "SI") | |
1748 (set_attr "length" "4,8")]) | |
1749 | |
1750 ;; Split *mul_sub_si if both the source and destination accumulator | |
1751 ;; values are GPRs. | |
1752 (define_split | |
1753 [(set (match_operand:SI 0 "d_operand") | |
1754 (minus:SI (match_operand:SI 1 "d_operand") | |
1755 (mult:SI (match_operand:SI 2 "d_operand") | |
1756 (match_operand:SI 3 "d_operand")))) | |
1757 (clobber (match_operand:SI 4 "lo_operand")) | |
1758 (clobber (match_operand:SI 5 "d_operand"))] | |
1759 "reload_completed" | |
1760 [(parallel [(set (match_dup 5) | |
1761 (mult:SI (match_dup 2) (match_dup 3))) | |
1762 (clobber (match_dup 4))]) | |
1763 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 5)))] | |
1764 "") | |
1765 | |
1766 (define_insn "*muls" | |
1767 [(set (match_operand:SI 0 "register_operand" "=l,d") | |
1768 (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") | |
1769 (match_operand:SI 2 "register_operand" "d,d")))) | |
1770 (clobber (match_scratch:SI 3 "=X,l"))] | |
1771 "ISA_HAS_MULS" | |
1772 "@ | |
1773 muls\t$0,%1,%2 | |
1774 muls\t%0,%1,%2" | |
1775 [(set_attr "type" "imul,imul3") | |
1776 (set_attr "mode" "SI")]) | |
1777 | |
1778 (define_expand "<u>mulsidi3" | |
1779 [(set (match_operand:DI 0 "register_operand") | |
1780 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) | |
1781 (any_extend:DI (match_operand:SI 2 "register_operand"))))] | |
1782 "!TARGET_64BIT || !TARGET_FIX_R4000" | |
1783 { | |
1784 if (TARGET_64BIT) | |
1785 emit_insn (gen_<u>mulsidi3_64bit (operands[0], operands[1], operands[2])); | |
1786 else if (TARGET_FIX_R4000) | |
1787 emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1], | |
1788 operands[2])); | |
1789 else | |
1790 emit_insn (gen_<u>mulsidi3_32bit (operands[0], operands[1], operands[2])); | |
1791 DONE; | |
1792 }) | |
1793 | |
1794 (define_insn "<u>mulsidi3_32bit" | |
1795 [(set (match_operand:DI 0 "register_operand" "=x") | |
1796 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1797 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))] | |
1798 "!TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DSPR2" | |
1799 "mult<u>\t%1,%2" | |
1800 [(set_attr "type" "imul") | |
1801 (set_attr "mode" "SI")]) | |
1802 | |
1803 (define_insn "<u>mulsidi3_32bit_r4000" | |
1804 [(set (match_operand:DI 0 "register_operand" "=d") | |
1805 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1806 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))) | |
1807 (clobber (match_scratch:DI 3 "=x"))] | |
1808 "!TARGET_64BIT && TARGET_FIX_R4000" | |
1809 "mult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0" | |
1810 [(set_attr "type" "imul") | |
1811 (set_attr "mode" "SI") | |
1812 (set_attr "length" "12")]) | |
1813 | |
1814 (define_insn_and_split "<u>mulsidi3_64bit" | |
1815 [(set (match_operand:DI 0 "register_operand" "=d") | |
1816 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1817 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))) | |
1818 (clobber (match_scratch:TI 3 "=x")) | |
1819 (clobber (match_scratch:DI 4 "=d"))] | |
1820 "TARGET_64BIT && !TARGET_FIX_R4000" | |
1821 "#" | |
1822 "&& reload_completed" | |
1823 [(set (match_dup 3) | |
1824 (unspec:TI [(mult:DI (any_extend:DI (match_dup 1)) | |
1825 (any_extend:DI (match_dup 2)))] | |
1826 UNSPEC_SET_HILO)) | |
1827 | |
1828 ;; OP4 <- LO, OP0 <- HI | |
1829 (set (match_dup 4) (match_dup 5)) | |
1830 (set (match_dup 0) (unspec:DI [(match_dup 3)] UNSPEC_MFHI)) | |
1831 | |
1832 ;; Zero-extend OP4. | |
1833 (set (match_dup 4) | |
1834 (ashift:DI (match_dup 4) | |
1835 (const_int 32))) | |
1836 (set (match_dup 4) | |
1837 (lshiftrt:DI (match_dup 4) | |
1838 (const_int 32))) | |
1839 | |
1840 ;; Shift OP0 into place. | |
1841 (set (match_dup 0) | |
1842 (ashift:DI (match_dup 0) | |
1843 (const_int 32))) | |
1844 | |
1845 ;; OR the two halves together | |
1846 (set (match_dup 0) | |
1847 (ior:DI (match_dup 0) | |
1848 (match_dup 4)))] | |
1849 { operands[5] = gen_rtx_REG (DImode, LO_REGNUM); } | |
1850 [(set_attr "type" "imul") | |
1851 (set_attr "mode" "SI") | |
1852 (set_attr "length" "24")]) | |
1853 | |
1854 (define_insn "<u>mulsidi3_64bit_hilo" | |
1855 [(set (match_operand:TI 0 "register_operand" "=x") | |
1856 (unspec:TI | |
1857 [(mult:DI | |
1858 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1859 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))] | |
1860 UNSPEC_SET_HILO))] | |
1861 "TARGET_64BIT && !TARGET_FIX_R4000" | |
1862 "mult<u>\t%1,%2" | |
1863 [(set_attr "type" "imul") | |
1864 (set_attr "mode" "SI")]) | |
1865 | |
1866 ;; Widening multiply with negation. | |
1867 (define_insn "*muls<u>_di" | |
1868 [(set (match_operand:DI 0 "register_operand" "=x") | |
1869 (neg:DI | |
1870 (mult:DI | |
1871 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1872 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] | |
1873 "!TARGET_64BIT && ISA_HAS_MULS" | |
1874 "muls<u>\t$0,%1,%2" | |
1875 [(set_attr "type" "imul") | |
1876 (set_attr "mode" "SI")]) | |
1877 | |
1878 (define_insn "<u>msubsidi4" | |
1879 [(set (match_operand:DI 0 "register_operand" "=ka") | |
1880 (minus:DI | |
1881 (match_operand:DI 3 "register_operand" "0") | |
1882 (mult:DI | |
1883 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1884 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] | |
1885 "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || ISA_HAS_DSPR2)" | |
1886 { | |
1887 if (ISA_HAS_DSPR2) | |
1888 return "msub<u>\t%q0,%1,%2"; | |
1889 else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB) | |
1890 return "msub<u>\t%1,%2"; | |
1891 else | |
1892 return "msac<u>\t$0,%1,%2"; | |
1893 } | |
1894 [(set_attr "type" "imadd") | |
1895 (set_attr "mode" "SI")]) | |
1896 | |
1897 ;; _highpart patterns | |
1898 | |
1899 (define_expand "<su>mulsi3_highpart" | |
1900 [(set (match_operand:SI 0 "register_operand") | |
1901 (truncate:SI | |
1902 (lshiftrt:DI | |
1903 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) | |
1904 (any_extend:DI (match_operand:SI 2 "register_operand"))) | |
1905 (const_int 32))))] | |
1906 "" | |
1907 { | |
1908 if (ISA_HAS_MULHI) | |
1909 emit_insn (gen_<su>mulsi3_highpart_mulhi_internal (operands[0], | |
1910 operands[1], | |
1911 operands[2])); | |
1912 else | |
1913 emit_insn (gen_<su>mulsi3_highpart_internal (operands[0], operands[1], | |
1914 operands[2])); | |
1915 DONE; | |
1916 }) | |
1917 | |
1918 (define_insn_and_split "<su>mulsi3_highpart_internal" | |
1919 [(set (match_operand:SI 0 "register_operand" "=d") | |
1920 (truncate:SI | |
1921 (lshiftrt:DI | |
1922 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1923 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) | |
1924 (const_int 32)))) | |
1925 (clobber (match_scratch:SI 3 "=l"))] | |
1926 "!ISA_HAS_MULHI" | |
1927 { return TARGET_FIX_R4000 ? "mult<u>\t%1,%2\n\tmfhi\t%0" : "#"; } | |
1928 "&& reload_completed && !TARGET_FIX_R4000" | |
1929 [(const_int 0)] | |
1930 { | |
1931 rtx hilo; | |
1932 | |
1933 if (TARGET_64BIT) | |
1934 { | |
1935 hilo = gen_rtx_REG (TImode, MD_REG_FIRST); | |
1936 emit_insn (gen_<u>mulsidi3_64bit_hilo (hilo, operands[1], operands[2])); | |
1937 emit_insn (gen_mfhisi_ti (operands[0], hilo)); | |
1938 } | |
1939 else | |
1940 { | |
1941 hilo = gen_rtx_REG (DImode, MD_REG_FIRST); | |
1942 emit_insn (gen_<u>mulsidi3_32bit (hilo, operands[1], operands[2])); | |
1943 emit_insn (gen_mfhisi_di (operands[0], hilo)); | |
1944 } | |
1945 DONE; | |
1946 } | |
1947 [(set_attr "type" "imul") | |
1948 (set_attr "mode" "SI") | |
1949 (set_attr "length" "8")]) | |
1950 | |
1951 (define_insn "<su>mulsi3_highpart_mulhi_internal" | |
1952 [(set (match_operand:SI 0 "register_operand" "=d") | |
1953 (truncate:SI | |
1954 (lshiftrt:DI | |
1955 (mult:DI | |
1956 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1957 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) | |
1958 (const_int 32)))) | |
1959 (clobber (match_scratch:SI 3 "=l"))] | |
1960 "ISA_HAS_MULHI" | |
1961 "mulhi<u>\t%0,%1,%2" | |
1962 [(set_attr "type" "imul3") | |
1963 (set_attr "mode" "SI")]) | |
1964 | |
1965 (define_insn "*<su>mulsi3_highpart_neg_mulhi_internal" | |
1966 [(set (match_operand:SI 0 "register_operand" "=d") | |
1967 (truncate:SI | |
1968 (lshiftrt:DI | |
1969 (neg:DI | |
1970 (mult:DI | |
1971 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1972 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))) | |
1973 (const_int 32)))) | |
1974 (clobber (match_scratch:SI 3 "=l"))] | |
1975 "ISA_HAS_MULHI" | |
1976 "mulshi<u>\t%0,%1,%2" | |
1977 [(set_attr "type" "imul3") | |
1978 (set_attr "mode" "SI")]) | |
1979 | |
1980 ;; Disable unsigned multiplication for -mfix-vr4120. This is for VR4120 | |
1981 ;; errata MD(0), which says that dmultu does not always produce the | |
1982 ;; correct result. | |
1983 (define_insn_and_split "<su>muldi3_highpart" | |
1984 [(set (match_operand:DI 0 "register_operand" "=d") | |
1985 (truncate:DI | |
1986 (lshiftrt:TI | |
1987 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d")) | |
1988 (any_extend:TI (match_operand:DI 2 "register_operand" "d"))) | |
1989 (const_int 64)))) | |
1990 (clobber (match_scratch:DI 3 "=l"))] | |
1991 "TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)" | |
1992 { return TARGET_FIX_R4000 ? "dmult<u>\t%1,%2\n\tmfhi\t%0" : "#"; } | |
1993 "&& reload_completed && !TARGET_FIX_R4000" | |
1994 [(const_int 0)] | |
1995 { | |
1996 rtx hilo; | |
1997 | |
1998 hilo = gen_rtx_REG (TImode, MD_REG_FIRST); | |
1999 emit_insn (gen_<u>mulditi3_internal (hilo, operands[1], operands[2])); | |
2000 emit_insn (gen_mfhidi_ti (operands[0], hilo)); | |
2001 DONE; | |
2002 } | |
2003 [(set_attr "type" "imul") | |
2004 (set_attr "mode" "DI") | |
2005 (set_attr "length" "8")]) | |
2006 | |
2007 (define_expand "<u>mulditi3" | |
2008 [(set (match_operand:TI 0 "register_operand") | |
2009 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand")) | |
2010 (any_extend:TI (match_operand:DI 2 "register_operand"))))] | |
2011 "TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)" | |
2012 { | |
2013 if (TARGET_FIX_R4000) | |
2014 emit_insn (gen_<u>mulditi3_r4000 (operands[0], operands[1], operands[2])); | |
2015 else | |
2016 emit_insn (gen_<u>mulditi3_internal (operands[0], operands[1], | |
2017 operands[2])); | |
2018 DONE; | |
2019 }) | |
2020 | |
2021 (define_insn "<u>mulditi3_internal" | |
2022 [(set (match_operand:TI 0 "register_operand" "=x") | |
2023 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d")) | |
2024 (any_extend:TI (match_operand:DI 2 "register_operand" "d"))))] | |
2025 "TARGET_64BIT | |
2026 && !TARGET_FIX_R4000 | |
2027 && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)" | |
2028 "dmult<u>\t%1,%2" | |
2029 [(set_attr "type" "imul") | |
2030 (set_attr "mode" "DI")]) | |
2031 | |
2032 (define_insn "<u>mulditi3_r4000" | |
2033 [(set (match_operand:TI 0 "register_operand" "=d") | |
2034 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d")) | |
2035 (any_extend:TI (match_operand:DI 2 "register_operand" "d")))) | |
2036 (clobber (match_scratch:TI 3 "=x"))] | |
2037 "TARGET_64BIT | |
2038 && TARGET_FIX_R4000 | |
2039 && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)" | |
2040 "dmult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0" | |
2041 [(set_attr "type" "imul") | |
2042 (set_attr "mode" "DI") | |
2043 (set_attr "length" "12")]) | |
2044 | |
2045 ;; The R4650 supports a 32-bit multiply/ 64-bit accumulate | |
2046 ;; instruction. The HI/LO registers are used as a 64-bit accumulator. | |
2047 | |
2048 (define_insn "madsi" | |
2049 [(set (match_operand:SI 0 "register_operand" "+l") | |
2050 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") | |
2051 (match_operand:SI 2 "register_operand" "d")) | |
2052 (match_dup 0)))] | |
2053 "TARGET_MAD" | |
2054 "mad\t%1,%2" | |
2055 [(set_attr "type" "imadd") | |
2056 (set_attr "mode" "SI")]) | |
2057 | |
2058 (define_insn "<u>maddsidi4" | |
2059 [(set (match_operand:DI 0 "register_operand" "=ka") | |
2060 (plus:DI | |
2061 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
2062 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) | |
2063 (match_operand:DI 3 "register_operand" "0")))] | |
2064 "(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || ISA_HAS_DSPR2) | |
2065 && !TARGET_64BIT" | |
2066 { | |
2067 if (TARGET_MAD) | |
2068 return "mad<u>\t%1,%2"; | |
2069 else if (ISA_HAS_DSPR2) | |
2070 return "madd<u>\t%q0,%1,%2"; | |
2071 else if (GENERATE_MADD_MSUB || TARGET_MIPS5500) | |
2072 return "madd<u>\t%1,%2"; | |
2073 else | |
2074 /* See comment in *macc. */ | |
2075 return "%[macc<u>\t%@,%1,%2%]"; | |
2076 } | |
2077 [(set_attr "type" "imadd") | |
2078 (set_attr "mode" "SI")]) | |
2079 | |
2080 ;; Floating point multiply accumulate instructions. | |
2081 | |
2082 (define_insn "*madd4<mode>" | |
2083 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2084 (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
2085 (match_operand:ANYF 2 "register_operand" "f")) | |
2086 (match_operand:ANYF 3 "register_operand" "f")))] | |
2087 "ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD" | |
2088 "madd.<fmt>\t%0,%3,%1,%2" | |
2089 [(set_attr "type" "fmadd") | |
2090 (set_attr "mode" "<UNITMODE>")]) | |
2091 | |
2092 (define_insn "*madd3<mode>" | |
2093 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2094 (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
2095 (match_operand:ANYF 2 "register_operand" "f")) | |
2096 (match_operand:ANYF 3 "register_operand" "0")))] | |
2097 "ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD" | |
2098 "madd.<fmt>\t%0,%1,%2" | |
2099 [(set_attr "type" "fmadd") | |
2100 (set_attr "mode" "<UNITMODE>")]) | |
2101 | |
2102 (define_insn "*msub4<mode>" | |
2103 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2104 (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
2105 (match_operand:ANYF 2 "register_operand" "f")) | |
2106 (match_operand:ANYF 3 "register_operand" "f")))] | |
2107 "ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD" | |
2108 "msub.<fmt>\t%0,%3,%1,%2" | |
2109 [(set_attr "type" "fmadd") | |
2110 (set_attr "mode" "<UNITMODE>")]) | |
2111 | |
2112 (define_insn "*msub3<mode>" | |
2113 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2114 (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
2115 (match_operand:ANYF 2 "register_operand" "f")) | |
2116 (match_operand:ANYF 3 "register_operand" "0")))] | |
2117 "ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD" | |
2118 "msub.<fmt>\t%0,%1,%2" | |
2119 [(set_attr "type" "fmadd") | |
2120 (set_attr "mode" "<UNITMODE>")]) | |
2121 | |
2122 (define_insn "*nmadd4<mode>" | |
2123 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2124 (neg:ANYF (plus:ANYF | |
2125 (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
2126 (match_operand:ANYF 2 "register_operand" "f")) | |
2127 (match_operand:ANYF 3 "register_operand" "f"))))] | |
2128 "ISA_HAS_NMADD4_NMSUB4 (<MODE>mode) | |
2129 && TARGET_FUSED_MADD | |
2130 && HONOR_SIGNED_ZEROS (<MODE>mode) | |
2131 && !HONOR_NANS (<MODE>mode)" | |
2132 "nmadd.<fmt>\t%0,%3,%1,%2" | |
2133 [(set_attr "type" "fmadd") | |
2134 (set_attr "mode" "<UNITMODE>")]) | |
2135 | |
2136 (define_insn "*nmadd3<mode>" | |
2137 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2138 (neg:ANYF (plus:ANYF | |
2139 (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
2140 (match_operand:ANYF 2 "register_operand" "f")) | |
2141 (match_operand:ANYF 3 "register_operand" "0"))))] | |
2142 "ISA_HAS_NMADD3_NMSUB3 (<MODE>mode) | |
2143 && TARGET_FUSED_MADD | |
2144 && HONOR_SIGNED_ZEROS (<MODE>mode) | |
2145 && !HONOR_NANS (<MODE>mode)" | |
2146 "nmadd.<fmt>\t%0,%1,%2" | |
2147 [(set_attr "type" "fmadd") | |
2148 (set_attr "mode" "<UNITMODE>")]) | |
2149 | |
2150 (define_insn "*nmadd4<mode>_fastmath" | |
2151 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2152 (minus:ANYF | |
2153 (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) | |
2154 (match_operand:ANYF 2 "register_operand" "f")) | |
2155 (match_operand:ANYF 3 "register_operand" "f")))] | |
2156 "ISA_HAS_NMADD4_NMSUB4 (<MODE>mode) | |
2157 && TARGET_FUSED_MADD | |
2158 && !HONOR_SIGNED_ZEROS (<MODE>mode) | |
2159 && !HONOR_NANS (<MODE>mode)" | |
2160 "nmadd.<fmt>\t%0,%3,%1,%2" | |
2161 [(set_attr "type" "fmadd") | |
2162 (set_attr "mode" "<UNITMODE>")]) | |
2163 | |
2164 (define_insn "*nmadd3<mode>_fastmath" | |
2165 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2166 (minus:ANYF | |
2167 (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) | |
2168 (match_operand:ANYF 2 "register_operand" "f")) | |
2169 (match_operand:ANYF 3 "register_operand" "0")))] | |
2170 "ISA_HAS_NMADD3_NMSUB3 (<MODE>mode) | |
2171 && TARGET_FUSED_MADD | |
2172 && !HONOR_SIGNED_ZEROS (<MODE>mode) | |
2173 && !HONOR_NANS (<MODE>mode)" | |
2174 "nmadd.<fmt>\t%0,%1,%2" | |
2175 [(set_attr "type" "fmadd") | |
2176 (set_attr "mode" "<UNITMODE>")]) | |
2177 | |
2178 (define_insn "*nmsub4<mode>" | |
2179 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2180 (neg:ANYF (minus:ANYF | |
2181 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") | |
2182 (match_operand:ANYF 3 "register_operand" "f")) | |
2183 (match_operand:ANYF 1 "register_operand" "f"))))] | |
2184 "ISA_HAS_NMADD4_NMSUB4 (<MODE>mode) | |
2185 && TARGET_FUSED_MADD | |
2186 && HONOR_SIGNED_ZEROS (<MODE>mode) | |
2187 && !HONOR_NANS (<MODE>mode)" | |
2188 "nmsub.<fmt>\t%0,%1,%2,%3" | |
2189 [(set_attr "type" "fmadd") | |
2190 (set_attr "mode" "<UNITMODE>")]) | |
2191 | |
2192 (define_insn "*nmsub3<mode>" | |
2193 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2194 (neg:ANYF (minus:ANYF | |
2195 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") | |
2196 (match_operand:ANYF 3 "register_operand" "f")) | |
2197 (match_operand:ANYF 1 "register_operand" "0"))))] | |
2198 "ISA_HAS_NMADD3_NMSUB3 (<MODE>mode) | |
2199 && TARGET_FUSED_MADD | |
2200 && HONOR_SIGNED_ZEROS (<MODE>mode) | |
2201 && !HONOR_NANS (<MODE>mode)" | |
2202 "nmsub.<fmt>\t%0,%1,%2" | |
2203 [(set_attr "type" "fmadd") | |
2204 (set_attr "mode" "<UNITMODE>")]) | |
2205 | |
2206 (define_insn "*nmsub4<mode>_fastmath" | |
2207 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2208 (minus:ANYF | |
2209 (match_operand:ANYF 1 "register_operand" "f") | |
2210 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") | |
2211 (match_operand:ANYF 3 "register_operand" "f"))))] | |
2212 "ISA_HAS_NMADD4_NMSUB4 (<MODE>mode) | |
2213 && TARGET_FUSED_MADD | |
2214 && !HONOR_SIGNED_ZEROS (<MODE>mode) | |
2215 && !HONOR_NANS (<MODE>mode)" | |
2216 "nmsub.<fmt>\t%0,%1,%2,%3" | |
2217 [(set_attr "type" "fmadd") | |
2218 (set_attr "mode" "<UNITMODE>")]) | |
2219 | |
2220 (define_insn "*nmsub3<mode>_fastmath" | |
2221 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2222 (minus:ANYF | |
2223 (match_operand:ANYF 1 "register_operand" "f") | |
2224 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") | |
2225 (match_operand:ANYF 3 "register_operand" "0"))))] | |
2226 "ISA_HAS_NMADD3_NMSUB3 (<MODE>mode) | |
2227 && TARGET_FUSED_MADD | |
2228 && !HONOR_SIGNED_ZEROS (<MODE>mode) | |
2229 && !HONOR_NANS (<MODE>mode)" | |
2230 "nmsub.<fmt>\t%0,%1,%2" | |
2231 [(set_attr "type" "fmadd") | |
2232 (set_attr "mode" "<UNITMODE>")]) | |
2233 | |
2234 ;; | |
2235 ;; .................... | |
2236 ;; | |
2237 ;; DIVISION and REMAINDER | |
2238 ;; | |
2239 ;; .................... | |
2240 ;; | |
2241 | |
2242 (define_expand "div<mode>3" | |
2243 [(set (match_operand:ANYF 0 "register_operand") | |
2244 (div:ANYF (match_operand:ANYF 1 "reg_or_1_operand") | |
2245 (match_operand:ANYF 2 "register_operand")))] | |
2246 "<divide_condition>" | |
2247 { | |
2248 if (const_1_operand (operands[1], <MODE>mode)) | |
2249 if (!(<recip_condition> && flag_unsafe_math_optimizations)) | |
2250 operands[1] = force_reg (<MODE>mode, operands[1]); | |
2251 }) | |
2252 | |
2253 ;; These patterns work around the early SB-1 rev2 core "F1" erratum: | |
2254 ;; | |
2255 ;; If an mfc1 or dmfc1 happens to access the floating point register | |
2256 ;; file at the same time a long latency operation (div, sqrt, recip, | |
2257 ;; sqrt) iterates an intermediate result back through the floating | |
2258 ;; point register file bypass, then instead returning the correct | |
2259 ;; register value the mfc1 or dmfc1 operation returns the intermediate | |
2260 ;; result of the long latency operation. | |
2261 ;; | |
2262 ;; The workaround is to insert an unconditional 'mov' from/to the | |
2263 ;; long latency op destination register. | |
2264 | |
2265 (define_insn "*div<mode>3" | |
2266 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2267 (div:ANYF (match_operand:ANYF 1 "register_operand" "f") | |
2268 (match_operand:ANYF 2 "register_operand" "f")))] | |
2269 "<divide_condition>" | |
2270 { | |
2271 if (TARGET_FIX_SB1) | |
2272 return "div.<fmt>\t%0,%1,%2\;mov.<fmt>\t%0,%0"; | |
2273 else | |
2274 return "div.<fmt>\t%0,%1,%2"; | |
2275 } | |
2276 [(set_attr "type" "fdiv") | |
2277 (set_attr "mode" "<UNITMODE>") | |
2278 (set (attr "length") | |
2279 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) | |
2280 (const_int 8) | |
2281 (const_int 4)))]) | |
2282 | |
2283 (define_insn "*recip<mode>3" | |
2284 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2285 (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") | |
2286 (match_operand:ANYF 2 "register_operand" "f")))] | |
2287 "<recip_condition> && flag_unsafe_math_optimizations" | |
2288 { | |
2289 if (TARGET_FIX_SB1) | |
2290 return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; | |
2291 else | |
2292 return "recip.<fmt>\t%0,%2"; | |
2293 } | |
2294 [(set_attr "type" "frdiv") | |
2295 (set_attr "mode" "<UNITMODE>") | |
2296 (set (attr "length") | |
2297 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) | |
2298 (const_int 8) | |
2299 (const_int 4)))]) | |
2300 | |
2301 ;; VR4120 errata MD(A1): signed division instructions do not work correctly | |
2302 ;; with negative operands. We use special libgcc functions instead. | |
2303 (define_insn_and_split "divmod<mode>4" | |
2304 [(set (match_operand:GPR 0 "register_operand" "=l") | |
2305 (div:GPR (match_operand:GPR 1 "register_operand" "d") | |
2306 (match_operand:GPR 2 "register_operand" "d"))) | |
2307 (set (match_operand:GPR 3 "register_operand" "=d") | |
2308 (mod:GPR (match_dup 1) | |
2309 (match_dup 2)))] | |
2310 "!TARGET_FIX_VR4120" | |
2311 "#" | |
2312 "&& reload_completed" | |
2313 [(const_int 0)] | |
2314 { | |
2315 rtx hilo; | |
2316 | |
2317 if (TARGET_64BIT) | |
2318 { | |
2319 hilo = gen_rtx_REG (TImode, MD_REG_FIRST); | |
2320 emit_insn (gen_divmod<mode>4_hilo_ti (hilo, operands[1], operands[2])); | |
2321 emit_insn (gen_mfhi<mode>_ti (operands[3], hilo)); | |
2322 } | |
2323 else | |
2324 { | |
2325 hilo = gen_rtx_REG (DImode, MD_REG_FIRST); | |
2326 emit_insn (gen_divmod<mode>4_hilo_di (hilo, operands[1], operands[2])); | |
2327 emit_insn (gen_mfhi<mode>_di (operands[3], hilo)); | |
2328 } | |
2329 DONE; | |
2330 } | |
2331 [(set_attr "type" "idiv") | |
2332 (set_attr "mode" "<MODE>") | |
2333 (set_attr "length" "8")]) | |
2334 | |
2335 (define_insn_and_split "udivmod<mode>4" | |
2336 [(set (match_operand:GPR 0 "register_operand" "=l") | |
2337 (udiv:GPR (match_operand:GPR 1 "register_operand" "d") | |
2338 (match_operand:GPR 2 "register_operand" "d"))) | |
2339 (set (match_operand:GPR 3 "register_operand" "=d") | |
2340 (umod:GPR (match_dup 1) | |
2341 (match_dup 2)))] | |
2342 "" | |
2343 "#" | |
2344 "reload_completed" | |
2345 [(const_int 0)] | |
2346 { | |
2347 rtx hilo; | |
2348 | |
2349 if (TARGET_64BIT) | |
2350 { | |
2351 hilo = gen_rtx_REG (TImode, MD_REG_FIRST); | |
2352 emit_insn (gen_udivmod<mode>4_hilo_ti (hilo, operands[1], operands[2])); | |
2353 emit_insn (gen_mfhi<mode>_ti (operands[3], hilo)); | |
2354 } | |
2355 else | |
2356 { | |
2357 hilo = gen_rtx_REG (DImode, MD_REG_FIRST); | |
2358 emit_insn (gen_udivmod<mode>4_hilo_di (hilo, operands[1], operands[2])); | |
2359 emit_insn (gen_mfhi<mode>_di (operands[3], hilo)); | |
2360 } | |
2361 DONE; | |
2362 } | |
2363 [(set_attr "type" "idiv") | |
2364 (set_attr "mode" "<MODE>") | |
2365 (set_attr "length" "8")]) | |
2366 | |
2367 (define_insn "<u>divmod<GPR:mode>4_hilo_<HILO:mode>" | |
2368 [(set (match_operand:HILO 0 "register_operand" "=x") | |
2369 (unspec:HILO | |
2370 [(any_div:GPR (match_operand:GPR 1 "register_operand" "d") | |
2371 (match_operand:GPR 2 "register_operand" "d"))] | |
2372 UNSPEC_SET_HILO))] | |
2373 "" | |
2374 { return mips_output_division ("<GPR:d>div<u>\t%.,%1,%2", operands); } | |
2375 [(set_attr "type" "idiv") | |
2376 (set_attr "mode" "<GPR:MODE>")]) | |
2377 | |
2378 ;; | |
2379 ;; .................... | |
2380 ;; | |
2381 ;; SQUARE ROOT | |
2382 ;; | |
2383 ;; .................... | |
2384 | |
2385 ;; These patterns work around the early SB-1 rev2 core "F1" erratum (see | |
2386 ;; "*div[sd]f3" comment for details). | |
2387 | |
2388 (define_insn "sqrt<mode>2" | |
2389 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2390 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))] | |
2391 "<sqrt_condition>" | |
2392 { | |
2393 if (TARGET_FIX_SB1) | |
2394 return "sqrt.<fmt>\t%0,%1\;mov.<fmt>\t%0,%0"; | |
2395 else | |
2396 return "sqrt.<fmt>\t%0,%1"; | |
2397 } | |
2398 [(set_attr "type" "fsqrt") | |
2399 (set_attr "mode" "<UNITMODE>") | |
2400 (set (attr "length") | |
2401 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) | |
2402 (const_int 8) | |
2403 (const_int 4)))]) | |
2404 | |
2405 (define_insn "*rsqrt<mode>a" | |
2406 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2407 (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") | |
2408 (sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))] | |
2409 "<recip_condition> && flag_unsafe_math_optimizations" | |
2410 { | |
2411 if (TARGET_FIX_SB1) | |
2412 return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; | |
2413 else | |
2414 return "rsqrt.<fmt>\t%0,%2"; | |
2415 } | |
2416 [(set_attr "type" "frsqrt") | |
2417 (set_attr "mode" "<UNITMODE>") | |
2418 (set (attr "length") | |
2419 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) | |
2420 (const_int 8) | |
2421 (const_int 4)))]) | |
2422 | |
2423 (define_insn "*rsqrt<mode>b" | |
2424 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2425 (sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") | |
2426 (match_operand:ANYF 2 "register_operand" "f"))))] | |
2427 "<recip_condition> && flag_unsafe_math_optimizations" | |
2428 { | |
2429 if (TARGET_FIX_SB1) | |
2430 return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; | |
2431 else | |
2432 return "rsqrt.<fmt>\t%0,%2"; | |
2433 } | |
2434 [(set_attr "type" "frsqrt") | |
2435 (set_attr "mode" "<UNITMODE>") | |
2436 (set (attr "length") | |
2437 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) | |
2438 (const_int 8) | |
2439 (const_int 4)))]) | |
2440 | |
2441 ;; | |
2442 ;; .................... | |
2443 ;; | |
2444 ;; ABSOLUTE VALUE | |
2445 ;; | |
2446 ;; .................... | |
2447 | |
2448 ;; Do not use the integer abs macro instruction, since that signals an | |
2449 ;; exception on -2147483648 (sigh). | |
2450 | |
2451 ;; abs.fmt is an arithmetic instruction and treats all NaN inputs as | |
2452 ;; invalid; it does not clear their sign bits. We therefore can't use | |
2453 ;; abs.fmt if the signs of NaNs matter. | |
2454 | |
2455 (define_insn "abs<mode>2" | |
2456 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2457 (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))] | |
2458 "!HONOR_NANS (<MODE>mode)" | |
2459 "abs.<fmt>\t%0,%1" | |
2460 [(set_attr "type" "fabs") | |
2461 (set_attr "mode" "<UNITMODE>")]) | |
2462 | |
2463 ;; | |
2464 ;; ................... | |
2465 ;; | |
2466 ;; Count leading zeroes. | |
2467 ;; | |
2468 ;; ................... | |
2469 ;; | |
2470 | |
2471 (define_insn "clz<mode>2" | |
2472 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2473 (clz:GPR (match_operand:GPR 1 "register_operand" "d")))] | |
2474 "ISA_HAS_CLZ_CLO" | |
2475 "<d>clz\t%0,%1" | |
2476 [(set_attr "type" "clz") | |
2477 (set_attr "mode" "<MODE>")]) | |
2478 | |
2479 ;; | |
2480 ;; ................... | |
2481 ;; | |
2482 ;; Count number of set bits. | |
2483 ;; | |
2484 ;; ................... | |
2485 ;; | |
2486 | |
2487 (define_insn "popcount<mode>2" | |
2488 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2489 (popcount:GPR (match_operand:GPR 1 "register_operand" "d")))] | |
2490 "ISA_HAS_POP" | |
2491 "<d>pop\t%0,%1" | |
2492 [(set_attr "type" "pop") | |
2493 (set_attr "mode" "<MODE>")]) | |
2494 | |
2495 ;; | |
2496 ;; .................... | |
2497 ;; | |
2498 ;; NEGATION and ONE'S COMPLEMENT | |
2499 ;; | |
2500 ;; .................... | |
2501 | |
2502 (define_insn "negsi2" | |
2503 [(set (match_operand:SI 0 "register_operand" "=d") | |
2504 (neg:SI (match_operand:SI 1 "register_operand" "d")))] | |
2505 "" | |
2506 { | |
2507 if (TARGET_MIPS16) | |
2508 return "neg\t%0,%1"; | |
2509 else | |
2510 return "subu\t%0,%.,%1"; | |
2511 } | |
2512 [(set_attr "type" "arith") | |
2513 (set_attr "mode" "SI")]) | |
2514 | |
2515 (define_insn "negdi2" | |
2516 [(set (match_operand:DI 0 "register_operand" "=d") | |
2517 (neg:DI (match_operand:DI 1 "register_operand" "d")))] | |
2518 "TARGET_64BIT && !TARGET_MIPS16" | |
2519 "dsubu\t%0,%.,%1" | |
2520 [(set_attr "type" "arith") | |
2521 (set_attr "mode" "DI")]) | |
2522 | |
2523 ;; neg.fmt is an arithmetic instruction and treats all NaN inputs as | |
2524 ;; invalid; it does not flip their sign bit. We therefore can't use | |
2525 ;; neg.fmt if the signs of NaNs matter. | |
2526 | |
2527 (define_insn "neg<mode>2" | |
2528 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
2529 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))] | |
2530 "!HONOR_NANS (<MODE>mode)" | |
2531 "neg.<fmt>\t%0,%1" | |
2532 [(set_attr "type" "fneg") | |
2533 (set_attr "mode" "<UNITMODE>")]) | |
2534 | |
2535 (define_insn "one_cmpl<mode>2" | |
2536 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2537 (not:GPR (match_operand:GPR 1 "register_operand" "d")))] | |
2538 "" | |
2539 { | |
2540 if (TARGET_MIPS16) | |
2541 return "not\t%0,%1"; | |
2542 else | |
2543 return "nor\t%0,%.,%1"; | |
2544 } | |
2545 [(set_attr "type" "logical") | |
2546 (set_attr "mode" "<MODE>")]) | |
2547 | |
2548 ;; | |
2549 ;; .................... | |
2550 ;; | |
2551 ;; LOGICAL | |
2552 ;; | |
2553 ;; .................... | |
2554 ;; | |
2555 | |
2556 ;; Many of these instructions use trivial define_expands, because we | |
2557 ;; want to use a different set of constraints when TARGET_MIPS16. | |
2558 | |
2559 (define_expand "and<mode>3" | |
2560 [(set (match_operand:GPR 0 "register_operand") | |
2561 (and:GPR (match_operand:GPR 1 "register_operand") | |
2562 (match_operand:GPR 2 "uns_arith_operand")))] | |
2563 "" | |
2564 { | |
2565 if (TARGET_MIPS16) | |
2566 operands[2] = force_reg (<MODE>mode, operands[2]); | |
2567 }) | |
2568 | |
2569 (define_insn "*and<mode>3" | |
2570 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
2571 (and:GPR (match_operand:GPR 1 "register_operand" "%d,d") | |
2572 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] | |
2573 "!TARGET_MIPS16" | |
2574 "@ | |
2575 and\t%0,%1,%2 | |
2576 andi\t%0,%1,%x2" | |
2577 [(set_attr "type" "logical") | |
2578 (set_attr "mode" "<MODE>")]) | |
2579 | |
2580 (define_insn "*and<mode>3_mips16" | |
2581 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2582 (and:GPR (match_operand:GPR 1 "register_operand" "%0") | |
2583 (match_operand:GPR 2 "register_operand" "d")))] | |
2584 "TARGET_MIPS16" | |
2585 "and\t%0,%2" | |
2586 [(set_attr "type" "logical") | |
2587 (set_attr "mode" "<MODE>")]) | |
2588 | |
2589 (define_expand "ior<mode>3" | |
2590 [(set (match_operand:GPR 0 "register_operand") | |
2591 (ior:GPR (match_operand:GPR 1 "register_operand") | |
2592 (match_operand:GPR 2 "uns_arith_operand")))] | |
2593 "" | |
2594 { | |
2595 if (TARGET_MIPS16) | |
2596 operands[2] = force_reg (<MODE>mode, operands[2]); | |
2597 }) | |
2598 | |
2599 (define_insn "*ior<mode>3" | |
2600 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
2601 (ior:GPR (match_operand:GPR 1 "register_operand" "%d,d") | |
2602 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] | |
2603 "!TARGET_MIPS16" | |
2604 "@ | |
2605 or\t%0,%1,%2 | |
2606 ori\t%0,%1,%x2" | |
2607 [(set_attr "type" "logical") | |
2608 (set_attr "mode" "<MODE>")]) | |
2609 | |
2610 (define_insn "*ior<mode>3_mips16" | |
2611 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2612 (ior:GPR (match_operand:GPR 1 "register_operand" "%0") | |
2613 (match_operand:GPR 2 "register_operand" "d")))] | |
2614 "TARGET_MIPS16" | |
2615 "or\t%0,%2" | |
2616 [(set_attr "type" "logical") | |
2617 (set_attr "mode" "<MODE>")]) | |
2618 | |
2619 (define_expand "xor<mode>3" | |
2620 [(set (match_operand:GPR 0 "register_operand") | |
2621 (xor:GPR (match_operand:GPR 1 "register_operand") | |
2622 (match_operand:GPR 2 "uns_arith_operand")))] | |
2623 "" | |
2624 "") | |
2625 | |
2626 (define_insn "" | |
2627 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
2628 (xor:GPR (match_operand:GPR 1 "register_operand" "%d,d") | |
2629 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] | |
2630 "!TARGET_MIPS16" | |
2631 "@ | |
2632 xor\t%0,%1,%2 | |
2633 xori\t%0,%1,%x2" | |
2634 [(set_attr "type" "logical") | |
2635 (set_attr "mode" "<MODE>")]) | |
2636 | |
2637 (define_insn "" | |
2638 [(set (match_operand:GPR 0 "register_operand" "=d,t,t") | |
2639 (xor:GPR (match_operand:GPR 1 "register_operand" "%0,d,d") | |
2640 (match_operand:GPR 2 "uns_arith_operand" "d,K,d")))] | |
2641 "TARGET_MIPS16" | |
2642 "@ | |
2643 xor\t%0,%2 | |
2644 cmpi\t%1,%2 | |
2645 cmp\t%1,%2" | |
2646 [(set_attr "type" "logical,arith,arith") | |
2647 (set_attr "mode" "<MODE>") | |
2648 (set_attr_alternative "length" | |
2649 [(const_int 4) | |
2650 (if_then_else (match_operand:VOID 2 "m16_uimm8_1") | |
2651 (const_int 4) | |
2652 (const_int 8)) | |
2653 (const_int 4)])]) | |
2654 | |
2655 (define_insn "*nor<mode>3" | |
2656 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2657 (and:GPR (not:GPR (match_operand:GPR 1 "register_operand" "d")) | |
2658 (not:GPR (match_operand:GPR 2 "register_operand" "d"))))] | |
2659 "!TARGET_MIPS16" | |
2660 "nor\t%0,%1,%2" | |
2661 [(set_attr "type" "logical") | |
2662 (set_attr "mode" "<MODE>")]) | |
2663 | |
2664 ;; | |
2665 ;; .................... | |
2666 ;; | |
2667 ;; TRUNCATION | |
2668 ;; | |
2669 ;; .................... | |
2670 | |
2671 | |
2672 | |
2673 (define_insn "truncdfsf2" | |
2674 [(set (match_operand:SF 0 "register_operand" "=f") | |
2675 (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] | |
2676 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" | |
2677 "cvt.s.d\t%0,%1" | |
2678 [(set_attr "type" "fcvt") | |
2679 (set_attr "cnv_mode" "D2S") | |
2680 (set_attr "mode" "SF")]) | |
2681 | |
2682 ;; Integer truncation patterns. Truncating SImode values to smaller | |
2683 ;; modes is a no-op, as it is for most other GCC ports. Truncating | |
2684 ;; DImode values to SImode is not a no-op for TARGET_64BIT since we | |
2685 ;; need to make sure that the lower 32 bits are properly sign-extended | |
2686 ;; (see TRULY_NOOP_TRUNCATION). Truncating DImode values into modes | |
2687 ;; smaller than SImode is equivalent to two separate truncations: | |
2688 ;; | |
2689 ;; A B | |
2690 ;; DI ---> HI == DI ---> SI ---> HI | |
2691 ;; DI ---> QI == DI ---> SI ---> QI | |
2692 ;; | |
2693 ;; Step A needs a real instruction but step B does not. | |
2694 | |
2695 (define_insn "truncdisi2" | |
2696 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m") | |
2697 (truncate:SI (match_operand:DI 1 "register_operand" "d,d")))] | |
2698 "TARGET_64BIT" | |
2699 "@ | |
2700 sll\t%0,%1,0 | |
2701 sw\t%1,%0" | |
2702 [(set_attr "move_type" "sll0,store") | |
2703 (set_attr "mode" "SI")]) | |
2704 | |
2705 (define_insn "truncdihi2" | |
2706 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") | |
2707 (truncate:HI (match_operand:DI 1 "register_operand" "d,d")))] | |
2708 "TARGET_64BIT" | |
2709 "@ | |
2710 sll\t%0,%1,0 | |
2711 sh\t%1,%0" | |
2712 [(set_attr "move_type" "sll0,store") | |
2713 (set_attr "mode" "SI")]) | |
2714 | |
2715 (define_insn "truncdiqi2" | |
2716 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") | |
2717 (truncate:QI (match_operand:DI 1 "register_operand" "d,d")))] | |
2718 "TARGET_64BIT" | |
2719 "@ | |
2720 sll\t%0,%1,0 | |
2721 sb\t%1,%0" | |
2722 [(set_attr "move_type" "sll0,store") | |
2723 (set_attr "mode" "SI")]) | |
2724 | |
2725 ;; Combiner patterns to optimize shift/truncate combinations. | |
2726 | |
2727 (define_insn "*ashr_trunc<mode>" | |
2728 [(set (match_operand:SUBDI 0 "register_operand" "=d") | |
2729 (truncate:SUBDI | |
2730 (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") | |
2731 (match_operand:DI 2 "const_arith_operand" ""))))] | |
2732 "TARGET_64BIT && !TARGET_MIPS16 && IN_RANGE (INTVAL (operands[2]), 32, 63)" | |
2733 "dsra\t%0,%1,%2" | |
2734 [(set_attr "type" "shift") | |
2735 (set_attr "mode" "<MODE>")]) | |
2736 | |
2737 (define_insn "*lshr32_trunc<mode>" | |
2738 [(set (match_operand:SUBDI 0 "register_operand" "=d") | |
2739 (truncate:SUBDI | |
2740 (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") | |
2741 (const_int 32))))] | |
2742 "TARGET_64BIT && !TARGET_MIPS16" | |
2743 "dsra\t%0,%1,32" | |
2744 [(set_attr "type" "shift") | |
2745 (set_attr "mode" "<MODE>")]) | |
2746 | |
2747 ;; Logical shift by 32 or more results in proper SI values so | |
2748 ;; truncation is removed by the middle end. | |
2749 (define_insn "*<optab>_trunc<mode>_exts" | |
2750 [(set (match_operand:SUBDI 0 "register_operand" "=d") | |
2751 (truncate:SUBDI | |
2752 (any_shiftrt:DI (match_operand:DI 1 "register_operand" "d") | |
2753 (match_operand:DI 2 "const_arith_operand" ""))))] | |
2754 "ISA_HAS_EXTS && TARGET_64BIT && UINTVAL (operands[2]) < 32" | |
2755 "exts\t%0,%1,%2,31" | |
2756 [(set_attr "type" "arith") | |
2757 (set_attr "mode" "<MODE>")]) | |
2758 | |
2759 ;; Combiner patterns for truncate/sign_extend combinations. The SI versions | |
2760 ;; use the shift/truncate patterns above. | |
2761 | |
2762 (define_insn_and_split "*extenddi_truncate<mode>" | |
2763 [(set (match_operand:DI 0 "register_operand" "=d") | |
2764 (sign_extend:DI | |
2765 (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))] | |
2766 "TARGET_64BIT && !TARGET_MIPS16" | |
2767 "#" | |
2768 "&& reload_completed" | |
2769 [(set (match_dup 2) | |
2770 (ashift:DI (match_dup 1) | |
2771 (match_dup 3))) | |
2772 (set (match_dup 0) | |
2773 (ashiftrt:DI (match_dup 2) | |
2774 (match_dup 3)))] | |
2775 { | |
2776 operands[2] = gen_lowpart (DImode, operands[0]); | |
2777 operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode)); | |
2778 }) | |
2779 | |
2780 (define_insn_and_split "*extendsi_truncate<mode>" | |
2781 [(set (match_operand:SI 0 "register_operand" "=d") | |
2782 (sign_extend:SI | |
2783 (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))] | |
2784 "TARGET_64BIT && !TARGET_MIPS16" | |
2785 "#" | |
2786 "&& reload_completed" | |
2787 [(set (match_dup 2) | |
2788 (ashift:DI (match_dup 1) | |
2789 (match_dup 3))) | |
2790 (set (match_dup 0) | |
2791 (truncate:SI (ashiftrt:DI (match_dup 2) | |
2792 (match_dup 3))))] | |
2793 { | |
2794 operands[2] = gen_lowpart (DImode, operands[0]); | |
2795 operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode)); | |
2796 }) | |
2797 | |
2798 ;; Combiner patterns to optimize truncate/zero_extend combinations. | |
2799 | |
2800 (define_insn "*zero_extend<mode>_trunchi" | |
2801 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2802 (zero_extend:GPR | |
2803 (truncate:HI (match_operand:DI 1 "register_operand" "d"))))] | |
2804 "TARGET_64BIT && !TARGET_MIPS16" | |
2805 "andi\t%0,%1,0xffff" | |
2806 [(set_attr "type" "logical") | |
2807 (set_attr "mode" "<MODE>")]) | |
2808 | |
2809 (define_insn "*zero_extend<mode>_truncqi" | |
2810 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2811 (zero_extend:GPR | |
2812 (truncate:QI (match_operand:DI 1 "register_operand" "d"))))] | |
2813 "TARGET_64BIT && !TARGET_MIPS16" | |
2814 "andi\t%0,%1,0xff" | |
2815 [(set_attr "type" "logical") | |
2816 (set_attr "mode" "<MODE>")]) | |
2817 | |
2818 (define_insn "" | |
2819 [(set (match_operand:HI 0 "register_operand" "=d") | |
2820 (zero_extend:HI | |
2821 (truncate:QI (match_operand:DI 1 "register_operand" "d"))))] | |
2822 "TARGET_64BIT && !TARGET_MIPS16" | |
2823 "andi\t%0,%1,0xff" | |
2824 [(set_attr "type" "logical") | |
2825 (set_attr "mode" "HI")]) | |
2826 | |
2827 ;; | |
2828 ;; .................... | |
2829 ;; | |
2830 ;; ZERO EXTENSION | |
2831 ;; | |
2832 ;; .................... | |
2833 | |
2834 ;; Extension insns. | |
2835 | |
2836 (define_insn_and_split "zero_extendsidi2" | |
2837 [(set (match_operand:DI 0 "register_operand" "=d,d") | |
2838 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,W")))] | |
2839 "TARGET_64BIT" | |
2840 "@ | |
2841 # | |
2842 lwu\t%0,%1" | |
2843 "&& reload_completed && REG_P (operands[1])" | |
2844 [(set (match_dup 0) | |
2845 (ashift:DI (match_dup 1) (const_int 32))) | |
2846 (set (match_dup 0) | |
2847 (lshiftrt:DI (match_dup 0) (const_int 32)))] | |
2848 { operands[1] = gen_lowpart (DImode, operands[1]); } | |
2849 [(set_attr "move_type" "shift_shift,load") | |
2850 (set_attr "mode" "DI")]) | |
2851 | |
2852 ;; Combine is not allowed to convert this insn into a zero_extendsidi2 | |
2853 ;; because of TRULY_NOOP_TRUNCATION. | |
2854 | |
2855 (define_insn_and_split "*clear_upper32" | |
2856 [(set (match_operand:DI 0 "register_operand" "=d,d") | |
2857 (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,W") | |
2858 (const_int 4294967295)))] | |
2859 "TARGET_64BIT" | |
2860 { | |
2861 if (which_alternative == 0) | |
2862 return "#"; | |
2863 | |
2864 operands[1] = gen_lowpart (SImode, operands[1]); | |
2865 return "lwu\t%0,%1"; | |
2866 } | |
2867 "&& reload_completed && REG_P (operands[1])" | |
2868 [(set (match_dup 0) | |
2869 (ashift:DI (match_dup 1) (const_int 32))) | |
2870 (set (match_dup 0) | |
2871 (lshiftrt:DI (match_dup 0) (const_int 32)))] | |
2872 "" | |
2873 [(set_attr "move_type" "shift_shift,load") | |
2874 (set_attr "mode" "DI")]) | |
2875 | |
2876 (define_expand "zero_extend<SHORT:mode><GPR:mode>2" | |
2877 [(set (match_operand:GPR 0 "register_operand") | |
2878 (zero_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))] | |
2879 "" | |
2880 { | |
2881 if (TARGET_MIPS16 && !GENERATE_MIPS16E | |
2882 && !memory_operand (operands[1], <SHORT:MODE>mode)) | |
2883 { | |
2884 emit_insn (gen_and<GPR:mode>3 (operands[0], | |
2885 gen_lowpart (<GPR:MODE>mode, operands[1]), | |
2886 force_reg (<GPR:MODE>mode, | |
2887 GEN_INT (<SHORT:mask>)))); | |
2888 DONE; | |
2889 } | |
2890 }) | |
2891 | |
2892 (define_insn "*zero_extend<SHORT:mode><GPR:mode>2" | |
2893 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
2894 (zero_extend:GPR | |
2895 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] | |
2896 "!TARGET_MIPS16" | |
2897 "@ | |
2898 andi\t%0,%1,<SHORT:mask> | |
2899 l<SHORT:size>u\t%0,%1" | |
2900 [(set_attr "move_type" "andi,load") | |
2901 (set_attr "mode" "<GPR:MODE>")]) | |
2902 | |
2903 (define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16e" | |
2904 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2905 (zero_extend:GPR (match_operand:SHORT 1 "register_operand" "0")))] | |
2906 "GENERATE_MIPS16E" | |
2907 "ze<SHORT:size>\t%0" | |
2908 ;; This instruction is effectively a special encoding of ANDI. | |
2909 [(set_attr "move_type" "andi") | |
2910 (set_attr "mode" "<GPR:MODE>")]) | |
2911 | |
2912 (define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16" | |
2913 [(set (match_operand:GPR 0 "register_operand" "=d") | |
2914 (zero_extend:GPR (match_operand:SHORT 1 "memory_operand" "m")))] | |
2915 "TARGET_MIPS16" | |
2916 "l<SHORT:size>u\t%0,%1" | |
2917 [(set_attr "move_type" "load") | |
2918 (set_attr "mode" "<GPR:MODE>")]) | |
2919 | |
2920 (define_expand "zero_extendqihi2" | |
2921 [(set (match_operand:HI 0 "register_operand") | |
2922 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand")))] | |
2923 "" | |
2924 { | |
2925 if (TARGET_MIPS16 && !memory_operand (operands[1], QImode)) | |
2926 { | |
2927 emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]), | |
2928 operands[1])); | |
2929 DONE; | |
2930 } | |
2931 }) | |
2932 | |
2933 (define_insn "*zero_extendqihi2" | |
2934 [(set (match_operand:HI 0 "register_operand" "=d,d") | |
2935 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] | |
2936 "!TARGET_MIPS16" | |
2937 "@ | |
2938 andi\t%0,%1,0x00ff | |
2939 lbu\t%0,%1" | |
2940 [(set_attr "move_type" "andi,load") | |
2941 (set_attr "mode" "HI")]) | |
2942 | |
2943 (define_insn "*zero_extendqihi2_mips16" | |
2944 [(set (match_operand:HI 0 "register_operand" "=d") | |
2945 (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))] | |
2946 "TARGET_MIPS16" | |
2947 "lbu\t%0,%1" | |
2948 [(set_attr "move_type" "load") | |
2949 (set_attr "mode" "HI")]) | |
2950 | |
2951 ;; | |
2952 ;; .................... | |
2953 ;; | |
2954 ;; SIGN EXTENSION | |
2955 ;; | |
2956 ;; .................... | |
2957 | |
2958 ;; Extension insns. | |
2959 ;; Those for integer source operand are ordered widest source type first. | |
2960 | |
2961 ;; When TARGET_64BIT, all SImode integer registers should already be in | |
2962 ;; sign-extended form (see TRULY_NOOP_TRUNCATION and truncdisi2). We can | |
2963 ;; therefore get rid of register->register instructions if we constrain | |
2964 ;; the source to be in the same register as the destination. | |
2965 ;; | |
2966 ;; The register alternative has type "arith" so that the pre-reload | |
2967 ;; scheduler will treat it as a move. This reflects what happens if | |
2968 ;; the register alternative needs a reload. | |
2969 (define_insn_and_split "extendsidi2" | |
2970 [(set (match_operand:DI 0 "register_operand" "=d,d") | |
2971 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,m")))] | |
2972 "TARGET_64BIT" | |
2973 "@ | |
2974 # | |
2975 lw\t%0,%1" | |
2976 "&& reload_completed && register_operand (operands[1], VOIDmode)" | |
2977 [(const_int 0)] | |
2978 { | |
2979 emit_note (NOTE_INSN_DELETED); | |
2980 DONE; | |
2981 } | |
2982 [(set_attr "move_type" "move,load") | |
2983 (set_attr "mode" "DI")]) | |
2984 | |
2985 (define_expand "extend<SHORT:mode><GPR:mode>2" | |
2986 [(set (match_operand:GPR 0 "register_operand") | |
2987 (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))] | |
2988 "") | |
2989 | |
2990 (define_insn "*extend<SHORT:mode><GPR:mode>2_mips16e" | |
2991 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
2992 (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand" "0,m")))] | |
2993 "GENERATE_MIPS16E" | |
2994 "@ | |
2995 se<SHORT:size>\t%0 | |
2996 l<SHORT:size>\t%0,%1" | |
2997 [(set_attr "move_type" "signext,load") | |
2998 (set_attr "mode" "<GPR:MODE>")]) | |
2999 | |
3000 (define_insn_and_split "*extend<SHORT:mode><GPR:mode>2" | |
3001 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
3002 (sign_extend:GPR | |
3003 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] | |
3004 "!ISA_HAS_SEB_SEH && !GENERATE_MIPS16E" | |
3005 "@ | |
3006 # | |
3007 l<SHORT:size>\t%0,%1" | |
3008 "&& reload_completed && REG_P (operands[1])" | |
3009 [(set (match_dup 0) (ashift:GPR (match_dup 1) (match_dup 2))) | |
3010 (set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))] | |
3011 { | |
3012 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]); | |
3013 operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode) | |
3014 - GET_MODE_BITSIZE (<SHORT:MODE>mode)); | |
3015 } | |
3016 [(set_attr "move_type" "shift_shift,load") | |
3017 (set_attr "mode" "<GPR:MODE>")]) | |
3018 | |
3019 (define_insn "*extend<SHORT:mode><GPR:mode>2_se<SHORT:size>" | |
3020 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
3021 (sign_extend:GPR | |
3022 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] | |
3023 "ISA_HAS_SEB_SEH" | |
3024 "@ | |
3025 se<SHORT:size>\t%0,%1 | |
3026 l<SHORT:size>\t%0,%1" | |
3027 [(set_attr "move_type" "signext,load") | |
3028 (set_attr "mode" "<GPR:MODE>")]) | |
3029 | |
3030 (define_expand "extendqihi2" | |
3031 [(set (match_operand:HI 0 "register_operand") | |
3032 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand")))] | |
3033 "") | |
3034 | |
3035 (define_insn "*extendqihi2_mips16e" | |
3036 [(set (match_operand:HI 0 "register_operand" "=d,d") | |
3037 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,m")))] | |
3038 "GENERATE_MIPS16E" | |
3039 "@ | |
3040 seb\t%0 | |
3041 lb\t%0,%1" | |
3042 [(set_attr "move_type" "signext,load") | |
3043 (set_attr "mode" "SI")]) | |
3044 | |
3045 (define_insn_and_split "*extendqihi2" | |
3046 [(set (match_operand:HI 0 "register_operand" "=d,d") | |
3047 (sign_extend:HI | |
3048 (match_operand:QI 1 "nonimmediate_operand" "d,m")))] | |
3049 "!ISA_HAS_SEB_SEH && !GENERATE_MIPS16E" | |
3050 "@ | |
3051 # | |
3052 lb\t%0,%1" | |
3053 "&& reload_completed && REG_P (operands[1])" | |
3054 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) | |
3055 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))] | |
3056 { | |
3057 operands[0] = gen_lowpart (SImode, operands[0]); | |
3058 operands[1] = gen_lowpart (SImode, operands[1]); | |
3059 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode) | |
3060 - GET_MODE_BITSIZE (QImode)); | |
3061 } | |
3062 [(set_attr "move_type" "shift_shift,load") | |
3063 (set_attr "mode" "SI")]) | |
3064 | |
3065 (define_insn "*extendqihi2_seb" | |
3066 [(set (match_operand:HI 0 "register_operand" "=d,d") | |
3067 (sign_extend:HI | |
3068 (match_operand:QI 1 "nonimmediate_operand" "d,m")))] | |
3069 "ISA_HAS_SEB_SEH" | |
3070 "@ | |
3071 seb\t%0,%1 | |
3072 lb\t%0,%1" | |
3073 [(set_attr "move_type" "signext,load") | |
3074 (set_attr "mode" "SI")]) | |
3075 | |
3076 (define_insn "extendsfdf2" | |
3077 [(set (match_operand:DF 0 "register_operand" "=f") | |
3078 (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] | |
3079 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" | |
3080 "cvt.d.s\t%0,%1" | |
3081 [(set_attr "type" "fcvt") | |
3082 (set_attr "cnv_mode" "S2D") | |
3083 (set_attr "mode" "DF")]) | |
3084 | |
3085 ;; | |
3086 ;; .................... | |
3087 ;; | |
3088 ;; CONVERSIONS | |
3089 ;; | |
3090 ;; .................... | |
3091 | |
3092 (define_expand "fix_truncdfsi2" | |
3093 [(set (match_operand:SI 0 "register_operand") | |
3094 (fix:SI (match_operand:DF 1 "register_operand")))] | |
3095 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" | |
3096 { | |
3097 if (!ISA_HAS_TRUNC_W) | |
3098 { | |
3099 emit_insn (gen_fix_truncdfsi2_macro (operands[0], operands[1])); | |
3100 DONE; | |
3101 } | |
3102 }) | |
3103 | |
3104 (define_insn "fix_truncdfsi2_insn" | |
3105 [(set (match_operand:SI 0 "register_operand" "=f") | |
3106 (fix:SI (match_operand:DF 1 "register_operand" "f")))] | |
3107 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && ISA_HAS_TRUNC_W" | |
3108 "trunc.w.d %0,%1" | |
3109 [(set_attr "type" "fcvt") | |
3110 (set_attr "mode" "DF") | |
3111 (set_attr "cnv_mode" "D2I")]) | |
3112 | |
3113 (define_insn "fix_truncdfsi2_macro" | |
3114 [(set (match_operand:SI 0 "register_operand" "=f") | |
3115 (fix:SI (match_operand:DF 1 "register_operand" "f"))) | |
3116 (clobber (match_scratch:DF 2 "=d"))] | |
3117 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W" | |
3118 { | |
3119 if (set_nomacro) | |
3120 return ".set\tmacro\;trunc.w.d %0,%1,%2\;.set\tnomacro"; | |
3121 else | |
3122 return "trunc.w.d %0,%1,%2"; | |
3123 } | |
3124 [(set_attr "type" "fcvt") | |
3125 (set_attr "mode" "DF") | |
3126 (set_attr "cnv_mode" "D2I") | |
3127 (set_attr "length" "36")]) | |
3128 | |
3129 (define_expand "fix_truncsfsi2" | |
3130 [(set (match_operand:SI 0 "register_operand") | |
3131 (fix:SI (match_operand:SF 1 "register_operand")))] | |
3132 "TARGET_HARD_FLOAT" | |
3133 { | |
3134 if (!ISA_HAS_TRUNC_W) | |
3135 { | |
3136 emit_insn (gen_fix_truncsfsi2_macro (operands[0], operands[1])); | |
3137 DONE; | |
3138 } | |
3139 }) | |
3140 | |
3141 (define_insn "fix_truncsfsi2_insn" | |
3142 [(set (match_operand:SI 0 "register_operand" "=f") | |
3143 (fix:SI (match_operand:SF 1 "register_operand" "f")))] | |
3144 "TARGET_HARD_FLOAT && ISA_HAS_TRUNC_W" | |
3145 "trunc.w.s %0,%1" | |
3146 [(set_attr "type" "fcvt") | |
3147 (set_attr "mode" "SF") | |
3148 (set_attr "cnv_mode" "S2I")]) | |
3149 | |
3150 (define_insn "fix_truncsfsi2_macro" | |
3151 [(set (match_operand:SI 0 "register_operand" "=f") | |
3152 (fix:SI (match_operand:SF 1 "register_operand" "f"))) | |
3153 (clobber (match_scratch:SF 2 "=d"))] | |
3154 "TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W" | |
3155 { | |
3156 if (set_nomacro) | |
3157 return ".set\tmacro\;trunc.w.s %0,%1,%2\;.set\tnomacro"; | |
3158 else | |
3159 return "trunc.w.s %0,%1,%2"; | |
3160 } | |
3161 [(set_attr "type" "fcvt") | |
3162 (set_attr "mode" "SF") | |
3163 (set_attr "cnv_mode" "S2I") | |
3164 (set_attr "length" "36")]) | |
3165 | |
3166 | |
3167 (define_insn "fix_truncdfdi2" | |
3168 [(set (match_operand:DI 0 "register_operand" "=f") | |
3169 (fix:DI (match_operand:DF 1 "register_operand" "f")))] | |
3170 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" | |
3171 "trunc.l.d %0,%1" | |
3172 [(set_attr "type" "fcvt") | |
3173 (set_attr "mode" "DF") | |
3174 (set_attr "cnv_mode" "D2I")]) | |
3175 | |
3176 | |
3177 (define_insn "fix_truncsfdi2" | |
3178 [(set (match_operand:DI 0 "register_operand" "=f") | |
3179 (fix:DI (match_operand:SF 1 "register_operand" "f")))] | |
3180 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" | |
3181 "trunc.l.s %0,%1" | |
3182 [(set_attr "type" "fcvt") | |
3183 (set_attr "mode" "SF") | |
3184 (set_attr "cnv_mode" "S2I")]) | |
3185 | |
3186 | |
3187 (define_insn "floatsidf2" | |
3188 [(set (match_operand:DF 0 "register_operand" "=f") | |
3189 (float:DF (match_operand:SI 1 "register_operand" "f")))] | |
3190 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" | |
3191 "cvt.d.w\t%0,%1" | |
3192 [(set_attr "type" "fcvt") | |
3193 (set_attr "mode" "DF") | |
3194 (set_attr "cnv_mode" "I2D")]) | |
3195 | |
3196 | |
3197 (define_insn "floatdidf2" | |
3198 [(set (match_operand:DF 0 "register_operand" "=f") | |
3199 (float:DF (match_operand:DI 1 "register_operand" "f")))] | |
3200 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" | |
3201 "cvt.d.l\t%0,%1" | |
3202 [(set_attr "type" "fcvt") | |
3203 (set_attr "mode" "DF") | |
3204 (set_attr "cnv_mode" "I2D")]) | |
3205 | |
3206 | |
3207 (define_insn "floatsisf2" | |
3208 [(set (match_operand:SF 0 "register_operand" "=f") | |
3209 (float:SF (match_operand:SI 1 "register_operand" "f")))] | |
3210 "TARGET_HARD_FLOAT" | |
3211 "cvt.s.w\t%0,%1" | |
3212 [(set_attr "type" "fcvt") | |
3213 (set_attr "mode" "SF") | |
3214 (set_attr "cnv_mode" "I2S")]) | |
3215 | |
3216 | |
3217 (define_insn "floatdisf2" | |
3218 [(set (match_operand:SF 0 "register_operand" "=f") | |
3219 (float:SF (match_operand:DI 1 "register_operand" "f")))] | |
3220 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" | |
3221 "cvt.s.l\t%0,%1" | |
3222 [(set_attr "type" "fcvt") | |
3223 (set_attr "mode" "SF") | |
3224 (set_attr "cnv_mode" "I2S")]) | |
3225 | |
3226 | |
3227 (define_expand "fixuns_truncdfsi2" | |
3228 [(set (match_operand:SI 0 "register_operand") | |
3229 (unsigned_fix:SI (match_operand:DF 1 "register_operand")))] | |
3230 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" | |
3231 { | |
3232 rtx reg1 = gen_reg_rtx (DFmode); | |
3233 rtx reg2 = gen_reg_rtx (DFmode); | |
3234 rtx reg3 = gen_reg_rtx (SImode); | |
3235 rtx label1 = gen_label_rtx (); | |
3236 rtx label2 = gen_label_rtx (); | |
3237 REAL_VALUE_TYPE offset; | |
3238 | |
3239 real_2expN (&offset, 31, DFmode); | |
3240 | |
3241 if (reg1) /* Turn off complaints about unreached code. */ | |
3242 { | |
3243 mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); | |
3244 do_pending_stack_adjust (); | |
3245 | |
3246 emit_insn (gen_cmpdf (operands[1], reg1)); | |
3247 emit_jump_insn (gen_bge (label1)); | |
3248 | |
3249 emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1])); | |
3250 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, | |
3251 gen_rtx_LABEL_REF (VOIDmode, label2))); | |
3252 emit_barrier (); | |
3253 | |
3254 emit_label (label1); | |
3255 mips_emit_move (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); | |
3256 mips_emit_move (reg3, GEN_INT (trunc_int_for_mode | |
3257 (BITMASK_HIGH, SImode))); | |
3258 | |
3259 emit_insn (gen_fix_truncdfsi2 (operands[0], reg2)); | |
3260 emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); | |
3261 | |
3262 emit_label (label2); | |
3263 | |
3264 /* Allow REG_NOTES to be set on last insn (labels don't have enough | |
3265 fields, and can't be used for REG_NOTES anyway). */ | |
3266 emit_use (stack_pointer_rtx); | |
3267 DONE; | |
3268 } | |
3269 }) | |
3270 | |
3271 | |
3272 (define_expand "fixuns_truncdfdi2" | |
3273 [(set (match_operand:DI 0 "register_operand") | |
3274 (unsigned_fix:DI (match_operand:DF 1 "register_operand")))] | |
3275 "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" | |
3276 { | |
3277 rtx reg1 = gen_reg_rtx (DFmode); | |
3278 rtx reg2 = gen_reg_rtx (DFmode); | |
3279 rtx reg3 = gen_reg_rtx (DImode); | |
3280 rtx label1 = gen_label_rtx (); | |
3281 rtx label2 = gen_label_rtx (); | |
3282 REAL_VALUE_TYPE offset; | |
3283 | |
3284 real_2expN (&offset, 63, DFmode); | |
3285 | |
3286 mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); | |
3287 do_pending_stack_adjust (); | |
3288 | |
3289 emit_insn (gen_cmpdf (operands[1], reg1)); | |
3290 emit_jump_insn (gen_bge (label1)); | |
3291 | |
3292 emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1])); | |
3293 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, | |
3294 gen_rtx_LABEL_REF (VOIDmode, label2))); | |
3295 emit_barrier (); | |
3296 | |
3297 emit_label (label1); | |
3298 mips_emit_move (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); | |
3299 mips_emit_move (reg3, GEN_INT (BITMASK_HIGH)); | |
3300 emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); | |
3301 | |
3302 emit_insn (gen_fix_truncdfdi2 (operands[0], reg2)); | |
3303 emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); | |
3304 | |
3305 emit_label (label2); | |
3306 | |
3307 /* Allow REG_NOTES to be set on last insn (labels don't have enough | |
3308 fields, and can't be used for REG_NOTES anyway). */ | |
3309 emit_use (stack_pointer_rtx); | |
3310 DONE; | |
3311 }) | |
3312 | |
3313 | |
3314 (define_expand "fixuns_truncsfsi2" | |
3315 [(set (match_operand:SI 0 "register_operand") | |
3316 (unsigned_fix:SI (match_operand:SF 1 "register_operand")))] | |
3317 "TARGET_HARD_FLOAT" | |
3318 { | |
3319 rtx reg1 = gen_reg_rtx (SFmode); | |
3320 rtx reg2 = gen_reg_rtx (SFmode); | |
3321 rtx reg3 = gen_reg_rtx (SImode); | |
3322 rtx label1 = gen_label_rtx (); | |
3323 rtx label2 = gen_label_rtx (); | |
3324 REAL_VALUE_TYPE offset; | |
3325 | |
3326 real_2expN (&offset, 31, SFmode); | |
3327 | |
3328 mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); | |
3329 do_pending_stack_adjust (); | |
3330 | |
3331 emit_insn (gen_cmpsf (operands[1], reg1)); | |
3332 emit_jump_insn (gen_bge (label1)); | |
3333 | |
3334 emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1])); | |
3335 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, | |
3336 gen_rtx_LABEL_REF (VOIDmode, label2))); | |
3337 emit_barrier (); | |
3338 | |
3339 emit_label (label1); | |
3340 mips_emit_move (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); | |
3341 mips_emit_move (reg3, GEN_INT (trunc_int_for_mode | |
3342 (BITMASK_HIGH, SImode))); | |
3343 | |
3344 emit_insn (gen_fix_truncsfsi2 (operands[0], reg2)); | |
3345 emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); | |
3346 | |
3347 emit_label (label2); | |
3348 | |
3349 /* Allow REG_NOTES to be set on last insn (labels don't have enough | |
3350 fields, and can't be used for REG_NOTES anyway). */ | |
3351 emit_use (stack_pointer_rtx); | |
3352 DONE; | |
3353 }) | |
3354 | |
3355 | |
3356 (define_expand "fixuns_truncsfdi2" | |
3357 [(set (match_operand:DI 0 "register_operand") | |
3358 (unsigned_fix:DI (match_operand:SF 1 "register_operand")))] | |
3359 "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" | |
3360 { | |
3361 rtx reg1 = gen_reg_rtx (SFmode); | |
3362 rtx reg2 = gen_reg_rtx (SFmode); | |
3363 rtx reg3 = gen_reg_rtx (DImode); | |
3364 rtx label1 = gen_label_rtx (); | |
3365 rtx label2 = gen_label_rtx (); | |
3366 REAL_VALUE_TYPE offset; | |
3367 | |
3368 real_2expN (&offset, 63, SFmode); | |
3369 | |
3370 mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); | |
3371 do_pending_stack_adjust (); | |
3372 | |
3373 emit_insn (gen_cmpsf (operands[1], reg1)); | |
3374 emit_jump_insn (gen_bge (label1)); | |
3375 | |
3376 emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1])); | |
3377 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, | |
3378 gen_rtx_LABEL_REF (VOIDmode, label2))); | |
3379 emit_barrier (); | |
3380 | |
3381 emit_label (label1); | |
3382 mips_emit_move (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); | |
3383 mips_emit_move (reg3, GEN_INT (BITMASK_HIGH)); | |
3384 emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); | |
3385 | |
3386 emit_insn (gen_fix_truncsfdi2 (operands[0], reg2)); | |
3387 emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); | |
3388 | |
3389 emit_label (label2); | |
3390 | |
3391 /* Allow REG_NOTES to be set on last insn (labels don't have enough | |
3392 fields, and can't be used for REG_NOTES anyway). */ | |
3393 emit_use (stack_pointer_rtx); | |
3394 DONE; | |
3395 }) | |
3396 | |
3397 ;; | |
3398 ;; .................... | |
3399 ;; | |
3400 ;; DATA MOVEMENT | |
3401 ;; | |
3402 ;; .................... | |
3403 | |
3404 ;; Bit field extract patterns which use lwl/lwr or ldl/ldr. | |
3405 | |
3406 (define_expand "extv" | |
3407 [(set (match_operand 0 "register_operand") | |
3408 (sign_extract (match_operand 1 "nonimmediate_operand") | |
3409 (match_operand 2 "const_int_operand") | |
3410 (match_operand 3 "const_int_operand")))] | |
3411 "!TARGET_MIPS16" | |
3412 { | |
3413 if (mips_expand_ext_as_unaligned_load (operands[0], operands[1], | |
3414 INTVAL (operands[2]), | |
3415 INTVAL (operands[3]))) | |
3416 DONE; | |
3417 else if (register_operand (operands[1], GET_MODE (operands[0])) | |
3418 && ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32) | |
3419 { | |
3420 if (GET_MODE (operands[0]) == DImode) | |
3421 emit_insn (gen_extvdi (operands[0], operands[1], operands[2], | |
3422 operands[3])); | |
3423 else | |
3424 emit_insn (gen_extvsi (operands[0], operands[1], operands[2], | |
3425 operands[3])); | |
3426 DONE; | |
3427 } | |
3428 else | |
3429 FAIL; | |
3430 }) | |
3431 | |
3432 (define_insn "extv<mode>" | |
3433 [(set (match_operand:GPR 0 "register_operand" "=d") | |
3434 (sign_extract:GPR (match_operand:GPR 1 "register_operand" "d") | |
3435 (match_operand 2 "const_int_operand" "") | |
3436 (match_operand 3 "const_int_operand" "")))] | |
3437 "ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32" | |
3438 "exts\t%0,%1,%3,%m2" | |
3439 [(set_attr "type" "arith") | |
3440 (set_attr "mode" "<MODE>")]) | |
3441 | |
3442 | |
3443 (define_expand "extzv" | |
3444 [(set (match_operand 0 "register_operand") | |
3445 (zero_extract (match_operand 1 "nonimmediate_operand") | |
3446 (match_operand 2 "const_int_operand") | |
3447 (match_operand 3 "const_int_operand")))] | |
3448 "!TARGET_MIPS16" | |
3449 { | |
3450 if (mips_expand_ext_as_unaligned_load (operands[0], operands[1], | |
3451 INTVAL (operands[2]), | |
3452 INTVAL (operands[3]))) | |
3453 DONE; | |
3454 else if (mips_use_ins_ext_p (operands[1], INTVAL (operands[2]), | |
3455 INTVAL (operands[3]))) | |
3456 { | |
3457 if (GET_MODE (operands[0]) == DImode) | |
3458 emit_insn (gen_extzvdi (operands[0], operands[1], operands[2], | |
3459 operands[3])); | |
3460 else | |
3461 emit_insn (gen_extzvsi (operands[0], operands[1], operands[2], | |
3462 operands[3])); | |
3463 DONE; | |
3464 } | |
3465 else | |
3466 FAIL; | |
3467 }) | |
3468 | |
3469 (define_insn "extzv<mode>" | |
3470 [(set (match_operand:GPR 0 "register_operand" "=d") | |
3471 (zero_extract:GPR (match_operand:GPR 1 "register_operand" "d") | |
3472 (match_operand 2 "const_int_operand" "") | |
3473 (match_operand 3 "const_int_operand" "")))] | |
3474 "mips_use_ins_ext_p (operands[1], INTVAL (operands[2]), | |
3475 INTVAL (operands[3]))" | |
3476 "<d>ext\t%0,%1,%3,%2" | |
3477 [(set_attr "type" "arith") | |
3478 (set_attr "mode" "<MODE>")]) | |
3479 | |
3480 (define_insn "*extzv_trunc<mode>_exts" | |
3481 [(set (match_operand:GPR 0 "register_operand" "=d") | |
3482 (truncate:GPR | |
3483 (zero_extract:DI (match_operand:DI 1 "register_operand" "d") | |
3484 (match_operand 2 "const_int_operand" "") | |
3485 (match_operand 3 "const_int_operand" ""))))] | |
3486 "ISA_HAS_EXTS && TARGET_64BIT && IN_RANGE (INTVAL (operands[2]), 32, 63)" | |
3487 "exts\t%0,%1,%3,31" | |
3488 [(set_attr "type" "arith") | |
3489 (set_attr "mode" "<MODE>")]) | |
3490 | |
3491 | |
3492 (define_expand "insv" | |
3493 [(set (zero_extract (match_operand 0 "nonimmediate_operand") | |
3494 (match_operand 1 "immediate_operand") | |
3495 (match_operand 2 "immediate_operand")) | |
3496 (match_operand 3 "reg_or_0_operand"))] | |
3497 "!TARGET_MIPS16" | |
3498 { | |
3499 if (mips_expand_ins_as_unaligned_store (operands[0], operands[3], | |
3500 INTVAL (operands[1]), | |
3501 INTVAL (operands[2]))) | |
3502 DONE; | |
3503 else if (mips_use_ins_ext_p (operands[0], INTVAL (operands[1]), | |
3504 INTVAL (operands[2]))) | |
3505 { | |
3506 if (GET_MODE (operands[0]) == DImode) | |
3507 emit_insn (gen_insvdi (operands[0], operands[1], operands[2], | |
3508 operands[3])); | |
3509 else | |
3510 emit_insn (gen_insvsi (operands[0], operands[1], operands[2], | |
3511 operands[3])); | |
3512 DONE; | |
3513 } | |
3514 else | |
3515 FAIL; | |
3516 }) | |
3517 | |
3518 (define_insn "insv<mode>" | |
3519 [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d") | |
3520 (match_operand:SI 1 "immediate_operand" "I") | |
3521 (match_operand:SI 2 "immediate_operand" "I")) | |
3522 (match_operand:GPR 3 "reg_or_0_operand" "dJ"))] | |
3523 "mips_use_ins_ext_p (operands[0], INTVAL (operands[1]), | |
3524 INTVAL (operands[2]))" | |
3525 "<d>ins\t%0,%z3,%2,%1" | |
3526 [(set_attr "type" "arith") | |
3527 (set_attr "mode" "<MODE>")]) | |
3528 | |
3529 ;; Combiner pattern for cins (clear and insert bit field). We can | |
3530 ;; implement mask-and-shift-left operation with this. Note that if | |
3531 ;; the upper bit of the mask is set in an SImode operation, the mask | |
3532 ;; itself will be sign-extended. mask_low_and_shift_len will | |
3533 ;; therefore be greater than our threshold of 32. | |
3534 | |
3535 (define_insn "*cins<mode>" | |
3536 [(set (match_operand:GPR 0 "register_operand" "=d") | |
3537 (and:GPR | |
3538 (ashift:GPR (match_operand:GPR 1 "register_operand" "d") | |
3539 (match_operand:GPR 2 "const_int_operand" "")) | |
3540 (match_operand:GPR 3 "const_int_operand" "")))] | |
3541 "ISA_HAS_CINS | |
3542 && mask_low_and_shift_p (<MODE>mode, operands[3], operands[2], 32)" | |
3543 { | |
3544 operands[3] = | |
3545 GEN_INT (mask_low_and_shift_len (<MODE>mode, operands[3], operands[2])); | |
3546 return "cins\t%0,%1,%2,%m3"; | |
3547 } | |
3548 [(set_attr "type" "shift") | |
3549 (set_attr "mode" "<MODE>")]) | |
3550 | |
3551 ;; Unaligned word moves generated by the bit field patterns. | |
3552 ;; | |
3553 ;; As far as the rtl is concerned, both the left-part and right-part | |
3554 ;; instructions can access the whole field. However, the real operand | |
3555 ;; refers to just the first or the last byte (depending on endianness). | |
3556 ;; We therefore use two memory operands to each instruction, one to | |
3557 ;; describe the rtl effect and one to use in the assembly output. | |
3558 ;; | |
3559 ;; Operands 0 and 1 are the rtl-level target and source respectively. | |
3560 ;; This allows us to use the standard length calculations for the "load" | |
3561 ;; and "store" type attributes. | |
3562 | |
3563 (define_insn "mov_<load>l" | |
3564 [(set (match_operand:GPR 0 "register_operand" "=d") | |
3565 (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") | |
3566 (match_operand:QI 2 "memory_operand" "m")] | |
3567 UNSPEC_LOAD_LEFT))] | |
3568 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])" | |
3569 "<load>l\t%0,%2" | |
3570 [(set_attr "move_type" "load") | |
3571 (set_attr "mode" "<MODE>")]) | |
3572 | |
3573 (define_insn "mov_<load>r" | |
3574 [(set (match_operand:GPR 0 "register_operand" "=d") | |
3575 (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") | |
3576 (match_operand:QI 2 "memory_operand" "m") | |
3577 (match_operand:GPR 3 "register_operand" "0")] | |
3578 UNSPEC_LOAD_RIGHT))] | |
3579 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])" | |
3580 "<load>r\t%0,%2" | |
3581 [(set_attr "move_type" "load") | |
3582 (set_attr "mode" "<MODE>")]) | |
3583 | |
3584 (define_insn "mov_<store>l" | |
3585 [(set (match_operand:BLK 0 "memory_operand" "=m") | |
3586 (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") | |
3587 (match_operand:QI 2 "memory_operand" "m")] | |
3588 UNSPEC_STORE_LEFT))] | |
3589 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])" | |
3590 "<store>l\t%z1,%2" | |
3591 [(set_attr "move_type" "store") | |
3592 (set_attr "mode" "<MODE>")]) | |
3593 | |
3594 (define_insn "mov_<store>r" | |
3595 [(set (match_operand:BLK 0 "memory_operand" "+m") | |
3596 (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") | |
3597 (match_operand:QI 2 "memory_operand" "m") | |
3598 (match_dup 0)] | |
3599 UNSPEC_STORE_RIGHT))] | |
3600 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])" | |
3601 "<store>r\t%z1,%2" | |
3602 [(set_attr "move_type" "store") | |
3603 (set_attr "mode" "<MODE>")]) | |
3604 | |
3605 ;; An instruction to calculate the high part of a 64-bit SYMBOL_ABSOLUTE. | |
3606 ;; The required value is: | |
3607 ;; | |
3608 ;; (%highest(op1) << 48) + (%higher(op1) << 32) + (%hi(op1) << 16) | |
3609 ;; | |
3610 ;; which translates to: | |
3611 ;; | |
3612 ;; lui op0,%highest(op1) | |
3613 ;; daddiu op0,op0,%higher(op1) | |
3614 ;; dsll op0,op0,16 | |
3615 ;; daddiu op0,op0,%hi(op1) | |
3616 ;; dsll op0,op0,16 | |
3617 ;; | |
3618 ;; The split is deferred until after flow2 to allow the peephole2 below | |
3619 ;; to take effect. | |
3620 (define_insn_and_split "*lea_high64" | |
3621 [(set (match_operand:DI 0 "register_operand" "=d") | |
3622 (high:DI (match_operand:DI 1 "absolute_symbolic_operand" "")))] | |
3623 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS" | |
3624 "#" | |
3625 "&& epilogue_completed" | |
3626 [(set (match_dup 0) (high:DI (match_dup 2))) | |
3627 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 2))) | |
3628 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16))) | |
3629 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3))) | |
3630 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))] | |
3631 { | |
3632 operands[2] = mips_unspec_address (operands[1], SYMBOL_64_HIGH); | |
3633 operands[3] = mips_unspec_address (operands[1], SYMBOL_64_MID); | |
3634 } | |
3635 [(set_attr "length" "20")]) | |
3636 | |
3637 ;; Use a scratch register to reduce the latency of the above pattern | |
3638 ;; on superscalar machines. The optimized sequence is: | |
3639 ;; | |
3640 ;; lui op1,%highest(op2) | |
3641 ;; lui op0,%hi(op2) | |
3642 ;; daddiu op1,op1,%higher(op2) | |
3643 ;; dsll32 op1,op1,0 | |
3644 ;; daddu op1,op1,op0 | |
3645 (define_peephole2 | |
3646 [(set (match_operand:DI 1 "d_operand") | |
3647 (high:DI (match_operand:DI 2 "absolute_symbolic_operand"))) | |
3648 (match_scratch:DI 0 "d")] | |
3649 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS" | |
3650 [(set (match_dup 1) (high:DI (match_dup 3))) | |
3651 (set (match_dup 0) (high:DI (match_dup 4))) | |
3652 (set (match_dup 1) (lo_sum:DI (match_dup 1) (match_dup 3))) | |
3653 (set (match_dup 1) (ashift:DI (match_dup 1) (const_int 32))) | |
3654 (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 0)))] | |
3655 { | |
3656 operands[3] = mips_unspec_address (operands[2], SYMBOL_64_HIGH); | |
3657 operands[4] = mips_unspec_address (operands[2], SYMBOL_64_LOW); | |
3658 }) | |
3659 | |
3660 ;; On most targets, the expansion of (lo_sum (high X) X) for a 64-bit | |
3661 ;; SYMBOL_ABSOLUTE X will take 6 cycles. This next pattern allows combine | |
3662 ;; to merge the HIGH and LO_SUM parts of a move if the HIGH part is only | |
3663 ;; used once. We can then use the sequence: | |
3664 ;; | |
3665 ;; lui op0,%highest(op1) | |
3666 ;; lui op2,%hi(op1) | |
3667 ;; daddiu op0,op0,%higher(op1) | |
3668 ;; daddiu op2,op2,%lo(op1) | |
3669 ;; dsll32 op0,op0,0 | |
3670 ;; daddu op0,op0,op2 | |
3671 ;; | |
3672 ;; which takes 4 cycles on most superscalar targets. | |
3673 (define_insn_and_split "*lea64" | |
3674 [(set (match_operand:DI 0 "register_operand" "=d") | |
3675 (match_operand:DI 1 "absolute_symbolic_operand" "")) | |
3676 (clobber (match_scratch:DI 2 "=&d"))] | |
3677 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected" | |
3678 "#" | |
3679 "&& reload_completed" | |
3680 [(set (match_dup 0) (high:DI (match_dup 3))) | |
3681 (set (match_dup 2) (high:DI (match_dup 4))) | |
3682 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3))) | |
3683 (set (match_dup 2) (lo_sum:DI (match_dup 2) (match_dup 4))) | |
3684 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32))) | |
3685 (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))] | |
3686 { | |
3687 operands[3] = mips_unspec_address (operands[1], SYMBOL_64_HIGH); | |
3688 operands[4] = mips_unspec_address (operands[1], SYMBOL_64_LOW); | |
3689 } | |
3690 [(set_attr "length" "24")]) | |
3691 | |
3692 ;; Split HIGHs into: | |
3693 ;; | |
3694 ;; li op0,%hi(sym) | |
3695 ;; sll op0,16 | |
3696 ;; | |
3697 ;; on MIPS16 targets. | |
3698 (define_split | |
3699 [(set (match_operand:SI 0 "d_operand") | |
3700 (high:SI (match_operand:SI 1 "absolute_symbolic_operand")))] | |
3701 "TARGET_MIPS16 && reload_completed" | |
3702 [(set (match_dup 0) (match_dup 2)) | |
3703 (set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16)))] | |
3704 { | |
3705 operands[2] = mips_unspec_address (operands[1], SYMBOL_32_HIGH); | |
3706 }) | |
3707 | |
3708 ;; Insns to fetch a symbol from a big GOT. | |
3709 | |
3710 (define_insn_and_split "*xgot_hi<mode>" | |
3711 [(set (match_operand:P 0 "register_operand" "=d") | |
3712 (high:P (match_operand:P 1 "got_disp_operand" "")))] | |
3713 "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" | |
3714 "#" | |
3715 "&& reload_completed" | |
3716 [(set (match_dup 0) (high:P (match_dup 2))) | |
3717 (set (match_dup 0) (plus:P (match_dup 0) (match_dup 3)))] | |
3718 { | |
3719 operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_DISP); | |
3720 operands[3] = pic_offset_table_rtx; | |
3721 } | |
3722 [(set_attr "got" "xgot_high") | |
3723 (set_attr "mode" "<MODE>")]) | |
3724 | |
3725 (define_insn_and_split "*xgot_lo<mode>" | |
3726 [(set (match_operand:P 0 "register_operand" "=d") | |
3727 (lo_sum:P (match_operand:P 1 "register_operand" "d") | |
3728 (match_operand:P 2 "got_disp_operand" "")))] | |
3729 "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" | |
3730 "#" | |
3731 "&& reload_completed" | |
3732 [(set (match_dup 0) | |
3733 (unspec:P [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))] | |
3734 { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_DISP); } | |
3735 [(set_attr "got" "load") | |
3736 (set_attr "mode" "<MODE>")]) | |
3737 | |
3738 ;; Insns to fetch a symbol from a normal GOT. | |
3739 | |
3740 (define_insn_and_split "*got_disp<mode>" | |
3741 [(set (match_operand:P 0 "register_operand" "=d") | |
3742 (match_operand:P 1 "got_disp_operand" ""))] | |
3743 "TARGET_EXPLICIT_RELOCS && !mips_split_p[SYMBOL_GOT_DISP]" | |
3744 "#" | |
3745 "&& reload_completed" | |
3746 [(set (match_dup 0) (match_dup 2))] | |
3747 { operands[2] = mips_got_load (NULL, operands[1], SYMBOL_GOTOFF_DISP); } | |
3748 [(set_attr "got" "load") | |
3749 (set_attr "mode" "<MODE>")]) | |
3750 | |
3751 ;; Insns for loading the "page" part of a page/ofst address from the GOT. | |
3752 | |
3753 (define_insn_and_split "*got_page<mode>" | |
3754 [(set (match_operand:P 0 "register_operand" "=d") | |
3755 (high:P (match_operand:P 1 "got_page_ofst_operand" "")))] | |
3756 "TARGET_EXPLICIT_RELOCS && !mips_split_hi_p[SYMBOL_GOT_PAGE_OFST]" | |
3757 "#" | |
3758 "&& reload_completed" | |
3759 [(set (match_dup 0) (match_dup 2))] | |
3760 { operands[2] = mips_got_load (NULL, operands[1], SYMBOL_GOTOFF_PAGE); } | |
3761 [(set_attr "got" "load") | |
3762 (set_attr "mode" "<MODE>")]) | |
3763 | |
3764 ;; Convenience expander that generates the rhs of a load_got<mode> insn. | |
3765 (define_expand "unspec_got<mode>" | |
3766 [(unspec:P [(match_operand:P 0) | |
3767 (match_operand:P 1)] UNSPEC_LOAD_GOT)]) | |
3768 | |
3769 ;; Lower-level instructions for loading an address from the GOT. | |
3770 ;; We could use MEMs, but an unspec gives more optimization | |
3771 ;; opportunities. | |
3772 | |
3773 (define_insn "load_got<mode>" | |
3774 [(set (match_operand:P 0 "register_operand" "=d") | |
3775 (unspec:P [(match_operand:P 1 "register_operand" "d") | |
3776 (match_operand:P 2 "immediate_operand" "")] | |
3777 UNSPEC_LOAD_GOT))] | |
3778 "" | |
3779 "<load>\t%0,%R2(%1)" | |
3780 [(set_attr "got" "load") | |
3781 (set_attr "mode" "<MODE>")]) | |
3782 | |
3783 ;; Instructions for adding the low 16 bits of an address to a register. | |
3784 ;; Operand 2 is the address: mips_print_operand works out which relocation | |
3785 ;; should be applied. | |
3786 | |
3787 (define_insn "*low<mode>" | |
3788 [(set (match_operand:P 0 "register_operand" "=d") | |
3789 (lo_sum:P (match_operand:P 1 "register_operand" "d") | |
3790 (match_operand:P 2 "immediate_operand" "")))] | |
3791 "!TARGET_MIPS16" | |
3792 "<d>addiu\t%0,%1,%R2" | |
3793 [(set_attr "type" "arith") | |
3794 (set_attr "mode" "<MODE>")]) | |
3795 | |
3796 (define_insn "*low<mode>_mips16" | |
3797 [(set (match_operand:P 0 "register_operand" "=d") | |
3798 (lo_sum:P (match_operand:P 1 "register_operand" "0") | |
3799 (match_operand:P 2 "immediate_operand" "")))] | |
3800 "TARGET_MIPS16" | |
3801 "<d>addiu\t%0,%R2" | |
3802 [(set_attr "type" "arith") | |
3803 (set_attr "mode" "<MODE>") | |
3804 (set_attr "extended_mips16" "yes")]) | |
3805 | |
3806 ;; Expose MIPS16 uses of the global pointer after reload if the function | |
3807 ;; is responsible for setting up the register itself. | |
3808 (define_split | |
3809 [(set (match_operand:GPR 0 "d_operand") | |
3810 (const:GPR (unspec:GPR [(const_int 0)] UNSPEC_GP)))] | |
3811 "TARGET_MIPS16 && TARGET_USE_GOT && reload_completed" | |
3812 [(set (match_dup 0) (match_dup 1))] | |
3813 { operands[1] = pic_offset_table_rtx; }) | |
3814 | |
3815 ;; Allow combine to split complex const_int load sequences, using operand 2 | |
3816 ;; to store the intermediate results. See move_operand for details. | |
3817 (define_split | |
3818 [(set (match_operand:GPR 0 "register_operand") | |
3819 (match_operand:GPR 1 "splittable_const_int_operand")) | |
3820 (clobber (match_operand:GPR 2 "register_operand"))] | |
3821 "" | |
3822 [(const_int 0)] | |
3823 { | |
3824 mips_move_integer (operands[2], operands[0], INTVAL (operands[1])); | |
3825 DONE; | |
3826 }) | |
3827 | |
3828 ;; Likewise, for symbolic operands. | |
3829 (define_split | |
3830 [(set (match_operand:P 0 "register_operand") | |
3831 (match_operand:P 1)) | |
3832 (clobber (match_operand:P 2 "register_operand"))] | |
3833 "mips_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)" | |
3834 [(set (match_dup 0) (match_dup 3))] | |
3835 { | |
3836 mips_split_symbol (operands[2], operands[1], | |
3837 MAX_MACHINE_MODE, &operands[3]); | |
3838 }) | |
3839 | |
3840 ;; 64-bit integer moves | |
3841 | |
3842 ;; Unlike most other insns, the move insns can't be split with | |
3843 ;; different predicates, because register spilling and other parts of | |
3844 ;; the compiler, have memoized the insn number already. | |
3845 | |
3846 (define_expand "movdi" | |
3847 [(set (match_operand:DI 0 "") | |
3848 (match_operand:DI 1 ""))] | |
3849 "" | |
3850 { | |
3851 if (mips_legitimize_move (DImode, operands[0], operands[1])) | |
3852 DONE; | |
3853 }) | |
3854 | |
3855 ;; For mips16, we need a special case to handle storing $31 into | |
3856 ;; memory, since we don't have a constraint to match $31. This | |
3857 ;; instruction can be generated by save_restore_insns. | |
3858 | |
3859 (define_insn "*mov<mode>_ra" | |
3860 [(set (match_operand:GPR 0 "stack_operand" "=m") | |
3861 (reg:GPR 31))] | |
3862 "TARGET_MIPS16" | |
3863 "<store>\t$31,%0" | |
3864 [(set_attr "move_type" "store") | |
3865 (set_attr "mode" "<MODE>")]) | |
3866 | |
3867 (define_insn "*movdi_32bit" | |
3868 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*f,*f,*d,*m,*B*C*D,*B*C*D,*d,*m") | |
3869 (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*J*d,*m,*f,*f,*d,*m,*B*C*D,*B*C*D"))] | |
3870 "!TARGET_64BIT && !TARGET_MIPS16 | |
3871 && (register_operand (operands[0], DImode) | |
3872 || reg_or_0_operand (operands[1], DImode))" | |
3873 { return mips_output_move (operands[0], operands[1]); } | |
3874 [(set_attr "move_type" "move,const,load,store,mthilo,mfhilo,mtc,fpload,mfc,fpstore,mtc,fpload,mfc,fpstore") | |
3875 (set_attr "mode" "DI")]) | |
3876 | |
3877 (define_insn "*movdi_32bit_mips16" | |
3878 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") | |
3879 (match_operand:DI 1 "move_operand" "d,d,y,K,N,m,d,*x"))] | |
3880 "!TARGET_64BIT && TARGET_MIPS16 | |
3881 && (register_operand (operands[0], DImode) | |
3882 || register_operand (operands[1], DImode))" | |
3883 { return mips_output_move (operands[0], operands[1]); } | |
3884 [(set_attr "move_type" "move,move,move,const,constN,load,store,mfhilo") | |
3885 (set_attr "mode" "DI")]) | |
3886 | |
3887 (define_insn "*movdi_64bit" | |
3888 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*a,*d,*B*C*D,*B*C*D,*d,*m") | |
3889 (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))] | |
3890 "TARGET_64BIT && !TARGET_MIPS16 | |
3891 && (register_operand (operands[0], DImode) | |
3892 || reg_or_0_operand (operands[1], DImode))" | |
3893 { return mips_output_move (operands[0], operands[1]); } | |
3894 [(set_attr "move_type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mthilo,mfhilo,mtc,fpload,mfc,fpstore") | |
3895 (set_attr "mode" "DI")]) | |
3896 | |
3897 (define_insn "*movdi_64bit_mips16" | |
3898 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m,*d") | |
3899 (match_operand:DI 1 "move_operand" "d,d,y,K,N,U,kf,m,d,*a"))] | |
3900 "TARGET_64BIT && TARGET_MIPS16 | |
3901 && (register_operand (operands[0], DImode) | |
3902 || register_operand (operands[1], DImode))" | |
3903 { return mips_output_move (operands[0], operands[1]); } | |
3904 [(set_attr "move_type" "move,move,move,const,constN,const,loadpool,load,store,mfhilo") | |
3905 (set_attr "mode" "DI")]) | |
3906 | |
3907 ;; On the mips16, we can split ld $r,N($r) into an add and a load, | |
3908 ;; when the original load is a 4 byte instruction but the add and the | |
3909 ;; load are 2 2 byte instructions. | |
3910 | |
3911 (define_split | |
3912 [(set (match_operand:DI 0 "d_operand") | |
3913 (mem:DI (plus:DI (match_dup 0) | |
3914 (match_operand:DI 1 "const_int_operand"))))] | |
3915 "TARGET_64BIT && TARGET_MIPS16 && reload_completed | |
3916 && !TARGET_DEBUG_D_MODE | |
3917 && ((INTVAL (operands[1]) < 0 | |
3918 && INTVAL (operands[1]) >= -0x10) | |
3919 || (INTVAL (operands[1]) >= 32 * 8 | |
3920 && INTVAL (operands[1]) <= 31 * 8 + 0x8) | |
3921 || (INTVAL (operands[1]) >= 0 | |
3922 && INTVAL (operands[1]) < 32 * 8 | |
3923 && (INTVAL (operands[1]) & 7) != 0))" | |
3924 [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) | |
3925 (set (match_dup 0) (mem:DI (plus:DI (match_dup 0) (match_dup 2))))] | |
3926 { | |
3927 HOST_WIDE_INT val = INTVAL (operands[1]); | |
3928 | |
3929 if (val < 0) | |
3930 operands[2] = const0_rtx; | |
3931 else if (val >= 32 * 8) | |
3932 { | |
3933 int off = val & 7; | |
3934 | |
3935 operands[1] = GEN_INT (0x8 + off); | |
3936 operands[2] = GEN_INT (val - off - 0x8); | |
3937 } | |
3938 else | |
3939 { | |
3940 int off = val & 7; | |
3941 | |
3942 operands[1] = GEN_INT (off); | |
3943 operands[2] = GEN_INT (val - off); | |
3944 } | |
3945 }) | |
3946 | |
3947 ;; 32-bit Integer moves | |
3948 | |
3949 ;; Unlike most other insns, the move insns can't be split with | |
3950 ;; different predicates, because register spilling and other parts of | |
3951 ;; the compiler, have memoized the insn number already. | |
3952 | |
3953 (define_expand "mov<mode>" | |
3954 [(set (match_operand:IMOVE32 0 "") | |
3955 (match_operand:IMOVE32 1 ""))] | |
3956 "" | |
3957 { | |
3958 if (mips_legitimize_move (<MODE>mode, operands[0], operands[1])) | |
3959 DONE; | |
3960 }) | |
3961 | |
3962 ;; The difference between these two is whether or not ints are allowed | |
3963 ;; in FP registers (off by default, use -mdebugh to enable). | |
3964 | |
3965 (define_insn "*mov<mode>_internal" | |
3966 [(set (match_operand:IMOVE32 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m") | |
3967 (match_operand:IMOVE32 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*z,*d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))] | |
3968 "!TARGET_MIPS16 | |
3969 && (register_operand (operands[0], <MODE>mode) | |
3970 || reg_or_0_operand (operands[1], <MODE>mode))" | |
3971 { return mips_output_move (operands[0], operands[1]); } | |
3972 [(set_attr "move_type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mfc,mtc,mthilo,mfhilo,mtc,fpload,mfc,fpstore") | |
3973 (set_attr "mode" "SI")]) | |
3974 | |
3975 (define_insn "*mov<mode>_mips16" | |
3976 [(set (match_operand:IMOVE32 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m,*d") | |
3977 (match_operand:IMOVE32 1 "move_operand" "d,d,y,K,N,U,kf,m,d,*a"))] | |
3978 "TARGET_MIPS16 | |
3979 && (register_operand (operands[0], <MODE>mode) | |
3980 || register_operand (operands[1], <MODE>mode))" | |
3981 { return mips_output_move (operands[0], operands[1]); } | |
3982 [(set_attr "move_type" "move,move,move,const,constN,const,loadpool,load,store,mfhilo") | |
3983 (set_attr "mode" "SI")]) | |
3984 | |
3985 ;; On the mips16, we can split lw $r,N($r) into an add and a load, | |
3986 ;; when the original load is a 4 byte instruction but the add and the | |
3987 ;; load are 2 2 byte instructions. | |
3988 | |
3989 (define_split | |
3990 [(set (match_operand:SI 0 "d_operand") | |
3991 (mem:SI (plus:SI (match_dup 0) | |
3992 (match_operand:SI 1 "const_int_operand"))))] | |
3993 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE | |
3994 && ((INTVAL (operands[1]) < 0 | |
3995 && INTVAL (operands[1]) >= -0x80) | |
3996 || (INTVAL (operands[1]) >= 32 * 4 | |
3997 && INTVAL (operands[1]) <= 31 * 4 + 0x7c) | |
3998 || (INTVAL (operands[1]) >= 0 | |
3999 && INTVAL (operands[1]) < 32 * 4 | |
4000 && (INTVAL (operands[1]) & 3) != 0))" | |
4001 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) | |
4002 (set (match_dup 0) (mem:SI (plus:SI (match_dup 0) (match_dup 2))))] | |
4003 { | |
4004 HOST_WIDE_INT val = INTVAL (operands[1]); | |
4005 | |
4006 if (val < 0) | |
4007 operands[2] = const0_rtx; | |
4008 else if (val >= 32 * 4) | |
4009 { | |
4010 int off = val & 3; | |
4011 | |
4012 operands[1] = GEN_INT (0x7c + off); | |
4013 operands[2] = GEN_INT (val - off - 0x7c); | |
4014 } | |
4015 else | |
4016 { | |
4017 int off = val & 3; | |
4018 | |
4019 operands[1] = GEN_INT (off); | |
4020 operands[2] = GEN_INT (val - off); | |
4021 } | |
4022 }) | |
4023 | |
4024 ;; On the mips16, we can split a load of certain constants into a load | |
4025 ;; and an add. This turns a 4 byte instruction into 2 2 byte | |
4026 ;; instructions. | |
4027 | |
4028 (define_split | |
4029 [(set (match_operand:SI 0 "d_operand") | |
4030 (match_operand:SI 1 "const_int_operand"))] | |
4031 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE | |
4032 && INTVAL (operands[1]) >= 0x100 | |
4033 && INTVAL (operands[1]) <= 0xff + 0x7f" | |
4034 [(set (match_dup 0) (match_dup 1)) | |
4035 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] | |
4036 { | |
4037 int val = INTVAL (operands[1]); | |
4038 | |
4039 operands[1] = GEN_INT (0xff); | |
4040 operands[2] = GEN_INT (val - 0xff); | |
4041 }) | |
4042 | |
4043 ;; This insn handles moving CCmode values. It's really just a | |
4044 ;; slightly simplified copy of movsi_internal2, with additional cases | |
4045 ;; to move a condition register to a general register and to move | |
4046 ;; between the general registers and the floating point registers. | |
4047 | |
4048 (define_insn "movcc" | |
4049 [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*m,*d,*f,*f,*f,*m") | |
4050 (match_operand:CC 1 "general_operand" "z,*d,*m,*d,*f,*d,*f,*m,*f"))] | |
4051 "ISA_HAS_8CC && TARGET_HARD_FLOAT" | |
4052 { return mips_output_move (operands[0], operands[1]); } | |
4053 [(set_attr "move_type" "lui_movf,move,load,store,mfc,mtc,fmove,fpload,fpstore") | |
4054 (set_attr "mode" "SI")]) | |
4055 | |
4056 ;; Reload condition code registers. reload_incc and reload_outcc | |
4057 ;; both handle moves from arbitrary operands into condition code | |
4058 ;; registers. reload_incc handles the more common case in which | |
4059 ;; a source operand is constrained to be in a condition-code | |
4060 ;; register, but has not been allocated to one. | |
4061 ;; | |
4062 ;; Sometimes, such as in movcc, we have a CCmode destination whose | |
4063 ;; constraints do not include 'z'. reload_outcc handles the case | |
4064 ;; when such an operand is allocated to a condition-code register. | |
4065 ;; | |
4066 ;; Note that reloads from a condition code register to some | |
4067 ;; other location can be done using ordinary moves. Moving | |
4068 ;; into a GPR takes a single movcc, moving elsewhere takes | |
4069 ;; two. We can leave these cases to the generic reload code. | |
4070 (define_expand "reload_incc" | |
4071 [(set (match_operand:CC 0 "fcc_reload_operand" "=z") | |
4072 (match_operand:CC 1 "general_operand" "")) | |
4073 (clobber (match_operand:TF 2 "register_operand" "=&f"))] | |
4074 "ISA_HAS_8CC && TARGET_HARD_FLOAT" | |
4075 { | |
4076 mips_expand_fcc_reload (operands[0], operands[1], operands[2]); | |
4077 DONE; | |
4078 }) | |
4079 | |
4080 (define_expand "reload_outcc" | |
4081 [(set (match_operand:CC 0 "fcc_reload_operand" "=z") | |
4082 (match_operand:CC 1 "register_operand" "")) | |
4083 (clobber (match_operand:TF 2 "register_operand" "=&f"))] | |
4084 "ISA_HAS_8CC && TARGET_HARD_FLOAT" | |
4085 { | |
4086 mips_expand_fcc_reload (operands[0], operands[1], operands[2]); | |
4087 DONE; | |
4088 }) | |
4089 | |
4090 ;; MIPS4 supports loading and storing a floating point register from | |
4091 ;; the sum of two general registers. We use two versions for each of | |
4092 ;; these four instructions: one where the two general registers are | |
4093 ;; SImode, and one where they are DImode. This is because general | |
4094 ;; registers will be in SImode when they hold 32-bit values, but, | |
4095 ;; since the 32-bit values are always sign extended, the [ls][wd]xc1 | |
4096 ;; instructions will still work correctly. | |
4097 | |
4098 ;; ??? Perhaps it would be better to support these instructions by | |
4099 ;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since | |
4100 ;; these instructions can only be used to load and store floating | |
4101 ;; point registers, that would probably cause trouble in reload. | |
4102 | |
4103 (define_insn "*<ANYF:loadx>_<P:mode>" | |
4104 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
4105 (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d") | |
4106 (match_operand:P 2 "register_operand" "d"))))] | |
4107 "ISA_HAS_FP4" | |
4108 "<ANYF:loadx>\t%0,%1(%2)" | |
4109 [(set_attr "type" "fpidxload") | |
4110 (set_attr "mode" "<ANYF:UNITMODE>")]) | |
4111 | |
4112 (define_insn "*<ANYF:storex>_<P:mode>" | |
4113 [(set (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d") | |
4114 (match_operand:P 2 "register_operand" "d"))) | |
4115 (match_operand:ANYF 0 "register_operand" "f"))] | |
4116 "ISA_HAS_FP4" | |
4117 "<ANYF:storex>\t%0,%1(%2)" | |
4118 [(set_attr "type" "fpidxstore") | |
4119 (set_attr "mode" "<ANYF:UNITMODE>")]) | |
4120 | |
4121 ;; Scaled indexed address load. | |
4122 ;; Per md.texi, we only need to look for a pattern with multiply in the | |
4123 ;; address expression, not shift. | |
4124 | |
4125 (define_insn "*lwxs" | |
4126 [(set (match_operand:IMOVE32 0 "register_operand" "=d") | |
4127 (mem:IMOVE32 | |
4128 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") | |
4129 (const_int 4)) | |
4130 (match_operand:SI 2 "register_operand" "d"))))] | |
4131 "ISA_HAS_LWXS" | |
4132 "lwxs\t%0,%1(%2)" | |
4133 [(set_attr "type" "load") | |
4134 (set_attr "mode" "SI")]) | |
4135 | |
4136 ;; 16-bit Integer moves | |
4137 | |
4138 ;; Unlike most other insns, the move insns can't be split with | |
4139 ;; different predicates, because register spilling and other parts of | |
4140 ;; the compiler, have memoized the insn number already. | |
4141 ;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. | |
4142 | |
4143 (define_expand "movhi" | |
4144 [(set (match_operand:HI 0 "") | |
4145 (match_operand:HI 1 ""))] | |
4146 "" | |
4147 { | |
4148 if (mips_legitimize_move (HImode, operands[0], operands[1])) | |
4149 DONE; | |
4150 }) | |
4151 | |
4152 (define_insn "*movhi_internal" | |
4153 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d") | |
4154 (match_operand:HI 1 "move_operand" "d,I,m,dJ,*d*J,*a"))] | |
4155 "!TARGET_MIPS16 | |
4156 && (register_operand (operands[0], HImode) | |
4157 || reg_or_0_operand (operands[1], HImode))" | |
4158 { return mips_output_move (operands[0], operands[1]); } | |
4159 [(set_attr "move_type" "move,const,load,store,mthilo,mfhilo") | |
4160 (set_attr "mode" "HI")]) | |
4161 | |
4162 (define_insn "*movhi_mips16" | |
4163 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") | |
4164 (match_operand:HI 1 "move_operand" "d,d,y,K,N,m,d,*a"))] | |
4165 "TARGET_MIPS16 | |
4166 && (register_operand (operands[0], HImode) | |
4167 || register_operand (operands[1], HImode))" | |
4168 { return mips_output_move (operands[0], operands[1]); } | |
4169 [(set_attr "move_type" "move,move,move,const,constN,load,store,mfhilo") | |
4170 (set_attr "mode" "HI")]) | |
4171 | |
4172 ;; On the mips16, we can split lh $r,N($r) into an add and a load, | |
4173 ;; when the original load is a 4 byte instruction but the add and the | |
4174 ;; load are 2 2 byte instructions. | |
4175 | |
4176 (define_split | |
4177 [(set (match_operand:HI 0 "d_operand") | |
4178 (mem:HI (plus:SI (match_dup 0) | |
4179 (match_operand:SI 1 "const_int_operand"))))] | |
4180 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE | |
4181 && ((INTVAL (operands[1]) < 0 | |
4182 && INTVAL (operands[1]) >= -0x80) | |
4183 || (INTVAL (operands[1]) >= 32 * 2 | |
4184 && INTVAL (operands[1]) <= 31 * 2 + 0x7e) | |
4185 || (INTVAL (operands[1]) >= 0 | |
4186 && INTVAL (operands[1]) < 32 * 2 | |
4187 && (INTVAL (operands[1]) & 1) != 0))" | |
4188 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) | |
4189 (set (match_dup 0) (mem:HI (plus:SI (match_dup 0) (match_dup 2))))] | |
4190 { | |
4191 HOST_WIDE_INT val = INTVAL (operands[1]); | |
4192 | |
4193 if (val < 0) | |
4194 operands[2] = const0_rtx; | |
4195 else if (val >= 32 * 2) | |
4196 { | |
4197 int off = val & 1; | |
4198 | |
4199 operands[1] = GEN_INT (0x7e + off); | |
4200 operands[2] = GEN_INT (val - off - 0x7e); | |
4201 } | |
4202 else | |
4203 { | |
4204 int off = val & 1; | |
4205 | |
4206 operands[1] = GEN_INT (off); | |
4207 operands[2] = GEN_INT (val - off); | |
4208 } | |
4209 }) | |
4210 | |
4211 ;; 8-bit Integer moves | |
4212 | |
4213 ;; Unlike most other insns, the move insns can't be split with | |
4214 ;; different predicates, because register spilling and other parts of | |
4215 ;; the compiler, have memoized the insn number already. | |
4216 ;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. | |
4217 | |
4218 (define_expand "movqi" | |
4219 [(set (match_operand:QI 0 "") | |
4220 (match_operand:QI 1 ""))] | |
4221 "" | |
4222 { | |
4223 if (mips_legitimize_move (QImode, operands[0], operands[1])) | |
4224 DONE; | |
4225 }) | |
4226 | |
4227 (define_insn "*movqi_internal" | |
4228 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d") | |
4229 (match_operand:QI 1 "move_operand" "d,I,m,dJ,*d*J,*a"))] | |
4230 "!TARGET_MIPS16 | |
4231 && (register_operand (operands[0], QImode) | |
4232 || reg_or_0_operand (operands[1], QImode))" | |
4233 { return mips_output_move (operands[0], operands[1]); } | |
4234 [(set_attr "move_type" "move,const,load,store,mthilo,mfhilo") | |
4235 (set_attr "mode" "QI")]) | |
4236 | |
4237 (define_insn "*movqi_mips16" | |
4238 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") | |
4239 (match_operand:QI 1 "move_operand" "d,d,y,K,N,m,d,*a"))] | |
4240 "TARGET_MIPS16 | |
4241 && (register_operand (operands[0], QImode) | |
4242 || register_operand (operands[1], QImode))" | |
4243 { return mips_output_move (operands[0], operands[1]); } | |
4244 [(set_attr "move_type" "move,move,move,const,constN,load,store,mfhilo") | |
4245 (set_attr "mode" "QI")]) | |
4246 | |
4247 ;; On the mips16, we can split lb $r,N($r) into an add and a load, | |
4248 ;; when the original load is a 4 byte instruction but the add and the | |
4249 ;; load are 2 2 byte instructions. | |
4250 | |
4251 (define_split | |
4252 [(set (match_operand:QI 0 "d_operand") | |
4253 (mem:QI (plus:SI (match_dup 0) | |
4254 (match_operand:SI 1 "const_int_operand"))))] | |
4255 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE | |
4256 && ((INTVAL (operands[1]) < 0 | |
4257 && INTVAL (operands[1]) >= -0x80) | |
4258 || (INTVAL (operands[1]) >= 32 | |
4259 && INTVAL (operands[1]) <= 31 + 0x7f))" | |
4260 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) | |
4261 (set (match_dup 0) (mem:QI (plus:SI (match_dup 0) (match_dup 2))))] | |
4262 { | |
4263 HOST_WIDE_INT val = INTVAL (operands[1]); | |
4264 | |
4265 if (val < 0) | |
4266 operands[2] = const0_rtx; | |
4267 else | |
4268 { | |
4269 operands[1] = GEN_INT (0x7f); | |
4270 operands[2] = GEN_INT (val - 0x7f); | |
4271 } | |
4272 }) | |
4273 | |
4274 ;; 32-bit floating point moves | |
4275 | |
4276 (define_expand "movsf" | |
4277 [(set (match_operand:SF 0 "") | |
4278 (match_operand:SF 1 ""))] | |
4279 "" | |
4280 { | |
4281 if (mips_legitimize_move (SFmode, operands[0], operands[1])) | |
4282 DONE; | |
4283 }) | |
4284 | |
4285 (define_insn "*movsf_hardfloat" | |
4286 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") | |
4287 (match_operand:SF 1 "move_operand" "f,G,m,f,G,*d,*f,*G*d,*m,*d"))] | |
4288 "TARGET_HARD_FLOAT | |
4289 && (register_operand (operands[0], SFmode) | |
4290 || reg_or_0_operand (operands[1], SFmode))" | |
4291 { return mips_output_move (operands[0], operands[1]); } | |
4292 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") | |
4293 (set_attr "mode" "SF")]) | |
4294 | |
4295 (define_insn "*movsf_softfloat" | |
4296 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m") | |
4297 (match_operand:SF 1 "move_operand" "Gd,m,d"))] | |
4298 "TARGET_SOFT_FLOAT && !TARGET_MIPS16 | |
4299 && (register_operand (operands[0], SFmode) | |
4300 || reg_or_0_operand (operands[1], SFmode))" | |
4301 { return mips_output_move (operands[0], operands[1]); } | |
4302 [(set_attr "move_type" "move,load,store") | |
4303 (set_attr "mode" "SF")]) | |
4304 | |
4305 (define_insn "*movsf_mips16" | |
4306 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,y,d,d,m") | |
4307 (match_operand:SF 1 "move_operand" "d,d,y,m,d"))] | |
4308 "TARGET_MIPS16 | |
4309 && (register_operand (operands[0], SFmode) | |
4310 || register_operand (operands[1], SFmode))" | |
4311 { return mips_output_move (operands[0], operands[1]); } | |
4312 [(set_attr "move_type" "move,move,move,load,store") | |
4313 (set_attr "mode" "SF")]) | |
4314 | |
4315 ;; 64-bit floating point moves | |
4316 | |
4317 (define_expand "movdf" | |
4318 [(set (match_operand:DF 0 "") | |
4319 (match_operand:DF 1 ""))] | |
4320 "" | |
4321 { | |
4322 if (mips_legitimize_move (DFmode, operands[0], operands[1])) | |
4323 DONE; | |
4324 }) | |
4325 | |
4326 (define_insn "*movdf_hardfloat" | |
4327 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") | |
4328 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))] | |
4329 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT | |
4330 && (register_operand (operands[0], DFmode) | |
4331 || reg_or_0_operand (operands[1], DFmode))" | |
4332 { return mips_output_move (operands[0], operands[1]); } | |
4333 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") | |
4334 (set_attr "mode" "DF")]) | |
4335 | |
4336 (define_insn "*movdf_softfloat" | |
4337 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,m") | |
4338 (match_operand:DF 1 "move_operand" "dG,m,dG"))] | |
4339 "(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16 | |
4340 && (register_operand (operands[0], DFmode) | |
4341 || reg_or_0_operand (operands[1], DFmode))" | |
4342 { return mips_output_move (operands[0], operands[1]); } | |
4343 [(set_attr "move_type" "move,load,store") | |
4344 (set_attr "mode" "DF")]) | |
4345 | |
4346 (define_insn "*movdf_mips16" | |
4347 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,y,d,d,m") | |
4348 (match_operand:DF 1 "move_operand" "d,d,y,m,d"))] | |
4349 "TARGET_MIPS16 | |
4350 && (register_operand (operands[0], DFmode) | |
4351 || register_operand (operands[1], DFmode))" | |
4352 { return mips_output_move (operands[0], operands[1]); } | |
4353 [(set_attr "move_type" "move,move,move,load,store") | |
4354 (set_attr "mode" "DF")]) | |
4355 | |
4356 ;; 128-bit integer moves | |
4357 | |
4358 (define_expand "movti" | |
4359 [(set (match_operand:TI 0) | |
4360 (match_operand:TI 1))] | |
4361 "TARGET_64BIT" | |
4362 { | |
4363 if (mips_legitimize_move (TImode, operands[0], operands[1])) | |
4364 DONE; | |
4365 }) | |
4366 | |
4367 (define_insn "*movti" | |
4368 [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d") | |
4369 (match_operand:TI 1 "move_operand" "d,i,m,dJ,*d*J,*a"))] | |
4370 "TARGET_64BIT | |
4371 && !TARGET_MIPS16 | |
4372 && (register_operand (operands[0], TImode) | |
4373 || reg_or_0_operand (operands[1], TImode))" | |
4374 "#" | |
4375 [(set_attr "move_type" "move,const,load,store,mthilo,mfhilo") | |
4376 (set_attr "mode" "TI")]) | |
4377 | |
4378 (define_insn "*movti_mips16" | |
4379 [(set (match_operand:TI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") | |
4380 (match_operand:TI 1 "move_operand" "d,d,y,K,N,m,d,*a"))] | |
4381 "TARGET_64BIT | |
4382 && TARGET_MIPS16 | |
4383 && (register_operand (operands[0], TImode) | |
4384 || register_operand (operands[1], TImode))" | |
4385 "#" | |
4386 [(set_attr "move_type" "move,move,move,const,constN,load,store,mfhilo") | |
4387 (set_attr "mode" "TI")]) | |
4388 | |
4389 ;; 128-bit floating point moves | |
4390 | |
4391 (define_expand "movtf" | |
4392 [(set (match_operand:TF 0) | |
4393 (match_operand:TF 1))] | |
4394 "TARGET_64BIT" | |
4395 { | |
4396 if (mips_legitimize_move (TFmode, operands[0], operands[1])) | |
4397 DONE; | |
4398 }) | |
4399 | |
4400 ;; This pattern handles both hard- and soft-float cases. | |
4401 (define_insn "*movtf" | |
4402 [(set (match_operand:TF 0 "nonimmediate_operand" "=d,d,m,f,d,f,m") | |
4403 (match_operand:TF 1 "move_operand" "dG,m,dG,dG,f,m,f"))] | |
4404 "TARGET_64BIT | |
4405 && !TARGET_MIPS16 | |
4406 && (register_operand (operands[0], TFmode) | |
4407 || reg_or_0_operand (operands[1], TFmode))" | |
4408 "#" | |
4409 [(set_attr "move_type" "move,load,store,mtc,mfc,fpload,fpstore") | |
4410 (set_attr "mode" "TF")]) | |
4411 | |
4412 (define_insn "*movtf_mips16" | |
4413 [(set (match_operand:TF 0 "nonimmediate_operand" "=d,y,d,d,m") | |
4414 (match_operand:TF 1 "move_operand" "d,d,y,m,d"))] | |
4415 "TARGET_64BIT | |
4416 && TARGET_MIPS16 | |
4417 && (register_operand (operands[0], TFmode) | |
4418 || register_operand (operands[1], TFmode))" | |
4419 "#" | |
4420 [(set_attr "move_type" "move,move,move,load,store") | |
4421 (set_attr "mode" "TF")]) | |
4422 | |
4423 (define_split | |
4424 [(set (match_operand:MOVE64 0 "nonimmediate_operand") | |
4425 (match_operand:MOVE64 1 "move_operand"))] | |
4426 "reload_completed && !TARGET_64BIT | |
4427 && mips_split_64bit_move_p (operands[0], operands[1])" | |
4428 [(const_int 0)] | |
4429 { | |
4430 mips_split_doubleword_move (operands[0], operands[1]); | |
4431 DONE; | |
4432 }) | |
4433 | |
4434 (define_split | |
4435 [(set (match_operand:MOVE128 0 "nonimmediate_operand") | |
4436 (match_operand:MOVE128 1 "move_operand"))] | |
4437 "TARGET_64BIT && reload_completed" | |
4438 [(const_int 0)] | |
4439 { | |
4440 mips_split_doubleword_move (operands[0], operands[1]); | |
4441 DONE; | |
4442 }) | |
4443 | |
4444 ;; When generating mips16 code, split moves of negative constants into | |
4445 ;; a positive "li" followed by a negation. | |
4446 (define_split | |
4447 [(set (match_operand 0 "d_operand") | |
4448 (match_operand 1 "const_int_operand"))] | |
4449 "TARGET_MIPS16 && reload_completed && INTVAL (operands[1]) < 0" | |
4450 [(set (match_dup 2) | |
4451 (match_dup 3)) | |
4452 (set (match_dup 2) | |
4453 (neg:SI (match_dup 2)))] | |
4454 { | |
4455 operands[2] = gen_lowpart (SImode, operands[0]); | |
4456 operands[3] = GEN_INT (-INTVAL (operands[1])); | |
4457 }) | |
4458 | |
4459 ;; 64-bit paired-single floating point moves | |
4460 | |
4461 (define_expand "movv2sf" | |
4462 [(set (match_operand:V2SF 0) | |
4463 (match_operand:V2SF 1))] | |
4464 "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" | |
4465 { | |
4466 if (mips_legitimize_move (V2SFmode, operands[0], operands[1])) | |
4467 DONE; | |
4468 }) | |
4469 | |
4470 (define_insn "*movv2sf" | |
4471 [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") | |
4472 (match_operand:V2SF 1 "move_operand" "f,YG,m,f,YG,*d,*f,*d*YG,*m,*d"))] | |
4473 "TARGET_HARD_FLOAT | |
4474 && TARGET_PAIRED_SINGLE_FLOAT | |
4475 && (register_operand (operands[0], V2SFmode) | |
4476 || reg_or_0_operand (operands[1], V2SFmode))" | |
4477 { return mips_output_move (operands[0], operands[1]); } | |
4478 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") | |
4479 (set_attr "mode" "DF")]) | |
4480 | |
4481 ;; Extract the high part of a HI/LO value. See mips_hard_regno_mode_ok_p | |
4482 ;; for the reason why we can't just use (reg:GPR HI_REGNUM). | |
4483 ;; | |
4484 ;; When generating VR4120 or VR4130 code, we use MACCHI and DMACCHI | |
4485 ;; instead of MFHI. This avoids both the normal MIPS III hi/lo hazards | |
4486 ;; and the errata related to -mfix-vr4130. | |
4487 (define_insn "mfhi<GPR:mode>_<HILO:mode>" | |
4488 [(set (match_operand:GPR 0 "register_operand" "=d") | |
4489 (unspec:GPR [(match_operand:HILO 1 "register_operand" "x")] | |
4490 UNSPEC_MFHI))] | |
4491 "" | |
4492 { return ISA_HAS_MACCHI ? "<GPR:d>macchi\t%0,%.,%." : "mfhi\t%0"; } | |
4493 [(set_attr "move_type" "mfhilo") | |
4494 (set_attr "mode" "<GPR:MODE>")]) | |
4495 | |
4496 ;; Set the high part of a HI/LO value, given that the low part has | |
4497 ;; already been set. See mips_hard_regno_mode_ok_p for the reason | |
4498 ;; why we can't just use (reg:GPR HI_REGNUM). | |
4499 (define_insn "mthi<GPR:mode>_<HILO:mode>" | |
4500 [(set (match_operand:HILO 0 "register_operand" "=x") | |
4501 (unspec:HILO [(match_operand:GPR 1 "reg_or_0_operand" "dJ") | |
4502 (match_operand:GPR 2 "register_operand" "l")] | |
4503 UNSPEC_MTHI))] | |
4504 "" | |
4505 "mthi\t%z1" | |
4506 [(set_attr "move_type" "mthilo") | |
4507 (set_attr "mode" "SI")]) | |
4508 | |
4509 ;; Emit a doubleword move in which exactly one of the operands is | |
4510 ;; a floating-point register. We can't just emit two normal moves | |
4511 ;; because of the constraints imposed by the FPU register model; | |
4512 ;; see mips_cannot_change_mode_class for details. Instead, we keep | |
4513 ;; the FPR whole and use special patterns to refer to each word of | |
4514 ;; the other operand. | |
4515 | |
4516 (define_expand "move_doubleword_fpr<mode>" | |
4517 [(set (match_operand:SPLITF 0) | |
4518 (match_operand:SPLITF 1))] | |
4519 "" | |
4520 { | |
4521 if (FP_REG_RTX_P (operands[0])) | |
4522 { | |
4523 rtx low = mips_subword (operands[1], 0); | |
4524 rtx high = mips_subword (operands[1], 1); | |
4525 emit_insn (gen_load_low<mode> (operands[0], low)); | |
4526 if (TARGET_FLOAT64 && !TARGET_64BIT) | |
4527 emit_insn (gen_mthc1<mode> (operands[0], high, operands[0])); | |
4528 else | |
4529 emit_insn (gen_load_high<mode> (operands[0], high, operands[0])); | |
4530 } | |
4531 else | |
4532 { | |
4533 rtx low = mips_subword (operands[0], 0); | |
4534 rtx high = mips_subword (operands[0], 1); | |
4535 emit_insn (gen_store_word<mode> (low, operands[1], const0_rtx)); | |
4536 if (TARGET_FLOAT64 && !TARGET_64BIT) | |
4537 emit_insn (gen_mfhc1<mode> (high, operands[1])); | |
4538 else | |
4539 emit_insn (gen_store_word<mode> (high, operands[1], const1_rtx)); | |
4540 } | |
4541 DONE; | |
4542 }) | |
4543 | |
4544 ;; Load the low word of operand 0 with operand 1. | |
4545 (define_insn "load_low<mode>" | |
4546 [(set (match_operand:SPLITF 0 "register_operand" "=f,f") | |
4547 (unspec:SPLITF [(match_operand:<HALFMODE> 1 "general_operand" "dJ,m")] | |
4548 UNSPEC_LOAD_LOW))] | |
4549 "TARGET_HARD_FLOAT" | |
4550 { | |
4551 operands[0] = mips_subword (operands[0], 0); | |
4552 return mips_output_move (operands[0], operands[1]); | |
4553 } | |
4554 [(set_attr "move_type" "mtc,fpload") | |
4555 (set_attr "mode" "<HALFMODE>")]) | |
4556 | |
4557 ;; Load the high word of operand 0 from operand 1, preserving the value | |
4558 ;; in the low word. | |
4559 (define_insn "load_high<mode>" | |
4560 [(set (match_operand:SPLITF 0 "register_operand" "=f,f") | |
4561 (unspec:SPLITF [(match_operand:<HALFMODE> 1 "general_operand" "dJ,m") | |
4562 (match_operand:SPLITF 2 "register_operand" "0,0")] | |
4563 UNSPEC_LOAD_HIGH))] | |
4564 "TARGET_HARD_FLOAT" | |
4565 { | |
4566 operands[0] = mips_subword (operands[0], 1); | |
4567 return mips_output_move (operands[0], operands[1]); | |
4568 } | |
4569 [(set_attr "move_type" "mtc,fpload") | |
4570 (set_attr "mode" "<HALFMODE>")]) | |
4571 | |
4572 ;; Store one word of operand 1 in operand 0. Operand 2 is 1 to store the | |
4573 ;; high word and 0 to store the low word. | |
4574 (define_insn "store_word<mode>" | |
4575 [(set (match_operand:<HALFMODE> 0 "nonimmediate_operand" "=d,m") | |
4576 (unspec:<HALFMODE> [(match_operand:SPLITF 1 "register_operand" "f,f") | |
4577 (match_operand 2 "const_int_operand")] | |
4578 UNSPEC_STORE_WORD))] | |
4579 "TARGET_HARD_FLOAT" | |
4580 { | |
4581 operands[1] = mips_subword (operands[1], INTVAL (operands[2])); | |
4582 return mips_output_move (operands[0], operands[1]); | |
4583 } | |
4584 [(set_attr "move_type" "mfc,fpstore") | |
4585 (set_attr "mode" "<HALFMODE>")]) | |
4586 | |
4587 ;; Move operand 1 to the high word of operand 0 using mthc1, preserving the | |
4588 ;; value in the low word. | |
4589 (define_insn "mthc1<mode>" | |
4590 [(set (match_operand:SPLITF 0 "register_operand" "=f") | |
4591 (unspec:SPLITF [(match_operand:<HALFMODE> 1 "reg_or_0_operand" "dJ") | |
4592 (match_operand:SPLITF 2 "register_operand" "0")] | |
4593 UNSPEC_MTHC1))] | |
4594 "TARGET_HARD_FLOAT && ISA_HAS_MXHC1" | |
4595 "mthc1\t%z1,%0" | |
4596 [(set_attr "move_type" "mtc") | |
4597 (set_attr "mode" "<HALFMODE>")]) | |
4598 | |
4599 ;; Move high word of operand 1 to operand 0 using mfhc1. | |
4600 (define_insn "mfhc1<mode>" | |
4601 [(set (match_operand:<HALFMODE> 0 "register_operand" "=d") | |
4602 (unspec:<HALFMODE> [(match_operand:SPLITF 1 "register_operand" "f")] | |
4603 UNSPEC_MFHC1))] | |
4604 "TARGET_HARD_FLOAT && ISA_HAS_MXHC1" | |
4605 "mfhc1\t%0,%1" | |
4606 [(set_attr "move_type" "mfc") | |
4607 (set_attr "mode" "<HALFMODE>")]) | |
4608 | |
4609 ;; Move a constant that satisfies CONST_GP_P into operand 0. | |
4610 (define_expand "load_const_gp_<mode>" | |
4611 [(set (match_operand:P 0 "register_operand" "=d") | |
4612 (const:P (unspec:P [(const_int 0)] UNSPEC_GP)))]) | |
4613 | |
4614 ;; Insn to initialize $gp for n32/n64 abicalls. Operand 0 is the offset | |
4615 ;; of _gp from the start of this function. Operand 1 is the incoming | |
4616 ;; function address. | |
4617 (define_insn_and_split "loadgp_newabi_<mode>" | |
4618 [(set (match_operand:P 0 "register_operand" "=d") | |
4619 (unspec_volatile:P [(match_operand:P 1) | |
4620 (match_operand:P 2 "register_operand" "d")] | |
4621 UNSPEC_LOADGP))] | |
4622 "mips_current_loadgp_style () == LOADGP_NEWABI" | |
4623 "#" | |
4624 "" | |
4625 [(set (match_dup 0) (match_dup 3)) | |
4626 (set (match_dup 0) (match_dup 4)) | |
4627 (set (match_dup 0) (match_dup 5))] | |
4628 { | |
4629 operands[3] = gen_rtx_HIGH (Pmode, operands[1]); | |
4630 operands[4] = gen_rtx_PLUS (Pmode, operands[0], operands[2]); | |
4631 operands[5] = gen_rtx_LO_SUM (Pmode, operands[0], operands[1]); | |
4632 } | |
4633 [(set_attr "length" "12")]) | |
4634 | |
4635 ;; Likewise, for -mno-shared code. Operand 0 is the __gnu_local_gp symbol. | |
4636 (define_insn_and_split "loadgp_absolute_<mode>" | |
4637 [(set (match_operand:P 0 "register_operand" "=d") | |
4638 (unspec_volatile:P [(match_operand:P 1)] UNSPEC_LOADGP))] | |
4639 "mips_current_loadgp_style () == LOADGP_ABSOLUTE" | |
4640 "#" | |
4641 "" | |
4642 [(const_int 0)] | |
4643 { | |
4644 mips_emit_move (operands[0], operands[1]); | |
4645 DONE; | |
4646 } | |
4647 [(set_attr "length" "8")]) | |
4648 | |
4649 ;; This blockage instruction prevents the gp load from being | |
4650 ;; scheduled after an implicit use of gp. It also prevents | |
4651 ;; the load from being deleted as dead. | |
4652 (define_insn "loadgp_blockage" | |
4653 [(unspec_volatile [(reg:SI 28)] UNSPEC_BLOCKAGE)] | |
4654 "" | |
4655 "" | |
4656 [(set_attr "type" "ghost") | |
4657 (set_attr "mode" "none")]) | |
4658 | |
4659 ;; Initialize $gp for RTP PIC. Operand 0 is the __GOTT_BASE__ symbol | |
4660 ;; and operand 1 is the __GOTT_INDEX__ symbol. | |
4661 (define_insn_and_split "loadgp_rtp_<mode>" | |
4662 [(set (match_operand:P 0 "register_operand" "=d") | |
4663 (unspec_volatile:P [(match_operand:P 1 "symbol_ref_operand") | |
4664 (match_operand:P 2 "symbol_ref_operand")] | |
4665 UNSPEC_LOADGP))] | |
4666 "mips_current_loadgp_style () == LOADGP_RTP" | |
4667 "#" | |
4668 "" | |
4669 [(set (match_dup 0) (high:P (match_dup 3))) | |
4670 (set (match_dup 0) (unspec:P [(match_dup 0) | |
4671 (match_dup 3)] UNSPEC_LOAD_GOT)) | |
4672 (set (match_dup 0) (unspec:P [(match_dup 0) | |
4673 (match_dup 4)] UNSPEC_LOAD_GOT))] | |
4674 { | |
4675 operands[3] = mips_unspec_address (operands[1], SYMBOL_ABSOLUTE); | |
4676 operands[4] = mips_unspec_address (operands[2], SYMBOL_HALF); | |
4677 } | |
4678 [(set_attr "length" "12")]) | |
4679 | |
4680 ;; Initialize the global pointer for MIPS16 code. Operand 0 is the | |
4681 ;; global pointer and operand 1 is the MIPS16 register that holds | |
4682 ;; the required value. | |
4683 (define_insn_and_split "copygp_mips16" | |
4684 [(set (match_operand:SI 0 "register_operand" "=y") | |
4685 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d")] | |
4686 UNSPEC_COPYGP))] | |
4687 "TARGET_MIPS16" | |
4688 "#" | |
4689 "&& reload_completed" | |
4690 [(set (match_dup 0) (match_dup 1))]) | |
4691 | |
4692 ;; Emit a .cprestore directive, which normally expands to a single store | |
4693 ;; instruction. Note that we continue to use .cprestore for explicit reloc | |
4694 ;; code so that jals inside inline asms will work correctly. | |
4695 (define_insn "cprestore" | |
4696 [(unspec_volatile [(match_operand 0 "const_int_operand" "I,i") | |
4697 (use (reg:SI 28))] | |
4698 UNSPEC_CPRESTORE)] | |
4699 "" | |
4700 { | |
4701 if (set_nomacro && which_alternative == 1) | |
4702 return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro"; | |
4703 else | |
4704 return ".cprestore\t%0"; | |
4705 } | |
4706 [(set_attr "type" "store") | |
4707 (set_attr "length" "4,12")]) | |
4708 | |
4709 ;; Expand in-line code to clear the instruction cache between operand[0] and | |
4710 ;; operand[1]. | |
4711 (define_expand "clear_cache" | |
4712 [(match_operand 0 "pmode_register_operand") | |
4713 (match_operand 1 "pmode_register_operand")] | |
4714 "" | |
4715 " | |
4716 { | |
4717 if (ISA_HAS_SYNCI) | |
4718 { | |
4719 mips_expand_synci_loop (operands[0], operands[1]); | |
4720 emit_insn (gen_sync ()); | |
4721 emit_insn (Pmode == SImode | |
4722 ? gen_clear_hazard_si () | |
4723 : gen_clear_hazard_di ()); | |
4724 } | |
4725 else if (mips_cache_flush_func && mips_cache_flush_func[0]) | |
4726 { | |
4727 rtx len = gen_reg_rtx (Pmode); | |
4728 emit_insn (gen_sub3_insn (len, operands[1], operands[0])); | |
4729 MIPS_ICACHE_SYNC (operands[0], len); | |
4730 } | |
4731 DONE; | |
4732 }") | |
4733 | |
4734 (define_insn "sync" | |
4735 [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)] | |
4736 "GENERATE_SYNC" | |
4737 "%|sync%-") | |
4738 | |
4739 (define_insn "synci" | |
4740 [(unspec_volatile [(match_operand 0 "pmode_register_operand" "d")] | |
4741 UNSPEC_SYNCI)] | |
4742 "ISA_HAS_SYNCI" | |
4743 "synci\t0(%0)") | |
4744 | |
4745 (define_insn "rdhwr_synci_step_<mode>" | |
4746 [(set (match_operand:P 0 "register_operand" "=d") | |
4747 (unspec_volatile [(const_int 1)] | |
4748 UNSPEC_RDHWR))] | |
4749 "ISA_HAS_SYNCI" | |
4750 "rdhwr\t%0,$1") | |
4751 | |
4752 (define_insn "clear_hazard_<mode>" | |
4753 [(unspec_volatile [(const_int 0)] UNSPEC_CLEAR_HAZARD) | |
4754 (clobber (reg:P 31))] | |
4755 "ISA_HAS_SYNCI" | |
4756 { | |
4757 return "%(%<bal\t1f\n" | |
4758 "\tnop\n" | |
4759 "1:\t<d>addiu\t$31,$31,12\n" | |
4760 "\tjr.hb\t$31\n" | |
4761 "\tnop%>%)"; | |
4762 } | |
4763 [(set_attr "length" "20")]) | |
4764 | |
4765 ;; Cache operations for R4000-style caches. | |
4766 (define_insn "mips_cache" | |
4767 [(set (mem:BLK (scratch)) | |
4768 (unspec:BLK [(match_operand:SI 0 "const_int_operand") | |
4769 (match_operand:QI 1 "address_operand" "p")] | |
4770 UNSPEC_MIPS_CACHE))] | |
4771 "ISA_HAS_CACHE" | |
4772 "cache\t%X0,%a1") | |
4773 | |
4774 ;; Similar, but with the operands hard-coded to an R10K cache barrier | |
4775 ;; operation. We keep the pattern distinct so that we can identify | |
4776 ;; cache operations inserted by -mr10k-cache-barrier=, and so that | |
4777 ;; the operation is never inserted into a delay slot. | |
4778 (define_insn "r10k_cache_barrier" | |
4779 [(set (mem:BLK (scratch)) | |
4780 (unspec:BLK [(const_int 0)] UNSPEC_R10K_CACHE_BARRIER))] | |
4781 "ISA_HAS_CACHE" | |
4782 "cache\t0x14,0(%$)" | |
4783 [(set_attr "can_delay" "no")]) | |
4784 | |
4785 ;; Block moves, see mips.c for more details. | |
4786 ;; Argument 0 is the destination | |
4787 ;; Argument 1 is the source | |
4788 ;; Argument 2 is the length | |
4789 ;; Argument 3 is the alignment | |
4790 | |
4791 (define_expand "movmemsi" | |
4792 [(parallel [(set (match_operand:BLK 0 "general_operand") | |
4793 (match_operand:BLK 1 "general_operand")) | |
4794 (use (match_operand:SI 2 "")) | |
4795 (use (match_operand:SI 3 "const_int_operand"))])] | |
4796 "!TARGET_MIPS16 && !TARGET_MEMCPY" | |
4797 { | |
4798 if (mips_expand_block_move (operands[0], operands[1], operands[2])) | |
4799 DONE; | |
4800 else | |
4801 FAIL; | |
4802 }) | |
4803 | |
4804 ;; | |
4805 ;; .................... | |
4806 ;; | |
4807 ;; SHIFTS | |
4808 ;; | |
4809 ;; .................... | |
4810 | |
4811 (define_expand "<optab><mode>3" | |
4812 [(set (match_operand:GPR 0 "register_operand") | |
4813 (any_shift:GPR (match_operand:GPR 1 "register_operand") | |
4814 (match_operand:SI 2 "arith_operand")))] | |
4815 "" | |
4816 { | |
4817 /* On the mips16, a shift of more than 8 is a four byte instruction, | |
4818 so, for a shift between 8 and 16, it is just as fast to do two | |
4819 shifts of 8 or less. If there is a lot of shifting going on, we | |
4820 may win in CSE. Otherwise combine will put the shifts back | |
4821 together again. This can be called by mips_function_arg, so we must | |
4822 be careful not to allocate a new register if we've reached the | |
4823 reload pass. */ | |
4824 if (TARGET_MIPS16 | |
4825 && optimize | |
4826 && GET_CODE (operands[2]) == CONST_INT | |
4827 && INTVAL (operands[2]) > 8 | |
4828 && INTVAL (operands[2]) <= 16 | |
4829 && !reload_in_progress | |
4830 && !reload_completed) | |
4831 { | |
4832 rtx temp = gen_reg_rtx (<MODE>mode); | |
4833 | |
4834 emit_insn (gen_<optab><mode>3 (temp, operands[1], GEN_INT (8))); | |
4835 emit_insn (gen_<optab><mode>3 (operands[0], temp, | |
4836 GEN_INT (INTVAL (operands[2]) - 8))); | |
4837 DONE; | |
4838 } | |
4839 }) | |
4840 | |
4841 (define_insn "*<optab><mode>3" | |
4842 [(set (match_operand:GPR 0 "register_operand" "=d") | |
4843 (any_shift:GPR (match_operand:GPR 1 "register_operand" "d") | |
4844 (match_operand:SI 2 "arith_operand" "dI")))] | |
4845 "!TARGET_MIPS16" | |
4846 { | |
4847 if (GET_CODE (operands[2]) == CONST_INT) | |
4848 operands[2] = GEN_INT (INTVAL (operands[2]) | |
4849 & (GET_MODE_BITSIZE (<MODE>mode) - 1)); | |
4850 | |
4851 return "<d><insn>\t%0,%1,%2"; | |
4852 } | |
4853 [(set_attr "type" "shift") | |
4854 (set_attr "mode" "<MODE>")]) | |
4855 | |
4856 (define_insn "*<optab>si3_extend" | |
4857 [(set (match_operand:DI 0 "register_operand" "=d") | |
4858 (sign_extend:DI | |
4859 (any_shift:SI (match_operand:SI 1 "register_operand" "d") | |
4860 (match_operand:SI 2 "arith_operand" "dI"))))] | |
4861 "TARGET_64BIT && !TARGET_MIPS16" | |
4862 { | |
4863 if (GET_CODE (operands[2]) == CONST_INT) | |
4864 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); | |
4865 | |
4866 return "<insn>\t%0,%1,%2"; | |
4867 } | |
4868 [(set_attr "type" "shift") | |
4869 (set_attr "mode" "SI")]) | |
4870 | |
4871 (define_insn "*<optab>si3_mips16" | |
4872 [(set (match_operand:SI 0 "register_operand" "=d,d") | |
4873 (any_shift:SI (match_operand:SI 1 "register_operand" "0,d") | |
4874 (match_operand:SI 2 "arith_operand" "d,I")))] | |
4875 "TARGET_MIPS16" | |
4876 { | |
4877 if (which_alternative == 0) | |
4878 return "<insn>\t%0,%2"; | |
4879 | |
4880 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); | |
4881 return "<insn>\t%0,%1,%2"; | |
4882 } | |
4883 [(set_attr "type" "shift") | |
4884 (set_attr "mode" "SI") | |
4885 (set_attr_alternative "length" | |
4886 [(const_int 4) | |
4887 (if_then_else (match_operand 2 "m16_uimm3_b") | |
4888 (const_int 4) | |
4889 (const_int 8))])]) | |
4890 | |
4891 ;; We need separate DImode MIPS16 patterns because of the irregularity | |
4892 ;; of right shifts. | |
4893 (define_insn "*ashldi3_mips16" | |
4894 [(set (match_operand:DI 0 "register_operand" "=d,d") | |
4895 (ashift:DI (match_operand:DI 1 "register_operand" "0,d") | |
4896 (match_operand:SI 2 "arith_operand" "d,I")))] | |
4897 "TARGET_64BIT && TARGET_MIPS16" | |
4898 { | |
4899 if (which_alternative == 0) | |
4900 return "dsll\t%0,%2"; | |
4901 | |
4902 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
4903 return "dsll\t%0,%1,%2"; | |
4904 } | |
4905 [(set_attr "type" "shift") | |
4906 (set_attr "mode" "DI") | |
4907 (set_attr_alternative "length" | |
4908 [(const_int 4) | |
4909 (if_then_else (match_operand 2 "m16_uimm3_b") | |
4910 (const_int 4) | |
4911 (const_int 8))])]) | |
4912 | |
4913 (define_insn "*ashrdi3_mips16" | |
4914 [(set (match_operand:DI 0 "register_operand" "=d,d") | |
4915 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0") | |
4916 (match_operand:SI 2 "arith_operand" "d,I")))] | |
4917 "TARGET_64BIT && TARGET_MIPS16" | |
4918 { | |
4919 if (GET_CODE (operands[2]) == CONST_INT) | |
4920 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
4921 | |
4922 return "dsra\t%0,%2"; | |
4923 } | |
4924 [(set_attr "type" "shift") | |
4925 (set_attr "mode" "DI") | |
4926 (set_attr_alternative "length" | |
4927 [(const_int 4) | |
4928 (if_then_else (match_operand 2 "m16_uimm3_b") | |
4929 (const_int 4) | |
4930 (const_int 8))])]) | |
4931 | |
4932 (define_insn "*lshrdi3_mips16" | |
4933 [(set (match_operand:DI 0 "register_operand" "=d,d") | |
4934 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0") | |
4935 (match_operand:SI 2 "arith_operand" "d,I")))] | |
4936 "TARGET_64BIT && TARGET_MIPS16" | |
4937 { | |
4938 if (GET_CODE (operands[2]) == CONST_INT) | |
4939 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
4940 | |
4941 return "dsrl\t%0,%2"; | |
4942 } | |
4943 [(set_attr "type" "shift") | |
4944 (set_attr "mode" "DI") | |
4945 (set_attr_alternative "length" | |
4946 [(const_int 4) | |
4947 (if_then_else (match_operand 2 "m16_uimm3_b") | |
4948 (const_int 4) | |
4949 (const_int 8))])]) | |
4950 | |
4951 ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. | |
4952 | |
4953 (define_split | |
4954 [(set (match_operand:GPR 0 "d_operand") | |
4955 (any_shift:GPR (match_operand:GPR 1 "d_operand") | |
4956 (match_operand:GPR 2 "const_int_operand")))] | |
4957 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE | |
4958 && INTVAL (operands[2]) > 8 | |
4959 && INTVAL (operands[2]) <= 16" | |
4960 [(set (match_dup 0) (any_shift:GPR (match_dup 1) (const_int 8))) | |
4961 (set (match_dup 0) (any_shift:GPR (match_dup 0) (match_dup 2)))] | |
4962 { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) | |
4963 | |
4964 ;; If we load a byte on the mips16 as a bitfield, the resulting | |
4965 ;; sequence of instructions is too complicated for combine, because it | |
4966 ;; involves four instructions: a load, a shift, a constant load into a | |
4967 ;; register, and an and (the key problem here is that the mips16 does | |
4968 ;; not have and immediate). We recognize a shift of a load in order | |
4969 ;; to make it simple enough for combine to understand. | |
4970 ;; | |
4971 ;; The length here is the worst case: the length of the split version | |
4972 ;; will be more accurate. | |
4973 (define_insn_and_split "" | |
4974 [(set (match_operand:SI 0 "register_operand" "=d") | |
4975 (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") | |
4976 (match_operand:SI 2 "immediate_operand" "I")))] | |
4977 "TARGET_MIPS16" | |
4978 "#" | |
4979 "" | |
4980 [(set (match_dup 0) (match_dup 1)) | |
4981 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))] | |
4982 "" | |
4983 [(set_attr "type" "load") | |
4984 (set_attr "mode" "SI") | |
4985 (set_attr "length" "16")]) | |
4986 | |
4987 (define_insn "rotr<mode>3" | |
4988 [(set (match_operand:GPR 0 "register_operand" "=d") | |
4989 (rotatert:GPR (match_operand:GPR 1 "register_operand" "d") | |
4990 (match_operand:SI 2 "arith_operand" "dI")))] | |
4991 "ISA_HAS_ROR" | |
4992 { | |
4993 if (GET_CODE (operands[2]) == CONST_INT) | |
4994 gcc_assert (INTVAL (operands[2]) >= 0 | |
4995 && INTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)); | |
4996 | |
4997 return "<d>ror\t%0,%1,%2"; | |
4998 } | |
4999 [(set_attr "type" "shift") | |
5000 (set_attr "mode" "<MODE>")]) | |
5001 | |
5002 ;; | |
5003 ;; .................... | |
5004 ;; | |
5005 ;; COMPARISONS | |
5006 ;; | |
5007 ;; .................... | |
5008 | |
5009 ;; Flow here is rather complex: | |
5010 ;; | |
5011 ;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments | |
5012 ;; into cmp_operands[] but generates no RTL. | |
5013 ;; | |
5014 ;; 2) The appropriate branch define_expand is called, which then | |
5015 ;; creates the appropriate RTL for the comparison and branch. | |
5016 ;; Different CC modes are used, based on what type of branch is | |
5017 ;; done, so that we can constrain things appropriately. There | |
5018 ;; are assumptions in the rest of GCC that break if we fold the | |
5019 ;; operands into the branches for integer operations, and use cc0 | |
5020 ;; for floating point, so we use the fp status register instead. | |
5021 ;; If needed, an appropriate temporary is created to hold the | |
5022 ;; of the integer compare. | |
5023 | |
5024 (define_expand "cmp<mode>" | |
5025 [(set (cc0) | |
5026 (compare:CC (match_operand:GPR 0 "register_operand") | |
5027 (match_operand:GPR 1 "nonmemory_operand")))] | |
5028 "" | |
5029 { | |
5030 cmp_operands[0] = operands[0]; | |
5031 cmp_operands[1] = operands[1]; | |
5032 DONE; | |
5033 }) | |
5034 | |
5035 (define_expand "cmp<mode>" | |
5036 [(set (cc0) | |
5037 (compare:CC (match_operand:SCALARF 0 "register_operand") | |
5038 (match_operand:SCALARF 1 "register_operand")))] | |
5039 "" | |
5040 { | |
5041 cmp_operands[0] = operands[0]; | |
5042 cmp_operands[1] = operands[1]; | |
5043 DONE; | |
5044 }) | |
5045 | |
5046 ;; | |
5047 ;; .................... | |
5048 ;; | |
5049 ;; CONDITIONAL BRANCHES | |
5050 ;; | |
5051 ;; .................... | |
5052 | |
5053 ;; Conditional branches on floating-point equality tests. | |
5054 | |
5055 (define_insn "*branch_fp" | |
5056 [(set (pc) | |
5057 (if_then_else | |
5058 (match_operator 0 "equality_operator" | |
5059 [(match_operand:CC 2 "register_operand" "z") | |
5060 (const_int 0)]) | |
5061 (label_ref (match_operand 1 "" "")) | |
5062 (pc)))] | |
5063 "TARGET_HARD_FLOAT" | |
5064 { | |
5065 return mips_output_conditional_branch (insn, operands, | |
5066 MIPS_BRANCH ("b%F0", "%Z2%1"), | |
5067 MIPS_BRANCH ("b%W0", "%Z2%1")); | |
5068 } | |
5069 [(set_attr "type" "branch") | |
5070 (set_attr "mode" "none")]) | |
5071 | |
5072 (define_insn "*branch_fp_inverted" | |
5073 [(set (pc) | |
5074 (if_then_else | |
5075 (match_operator 0 "equality_operator" | |
5076 [(match_operand:CC 2 "register_operand" "z") | |
5077 (const_int 0)]) | |
5078 (pc) | |
5079 (label_ref (match_operand 1 "" ""))))] | |
5080 "TARGET_HARD_FLOAT" | |
5081 { | |
5082 return mips_output_conditional_branch (insn, operands, | |
5083 MIPS_BRANCH ("b%W0", "%Z2%1"), | |
5084 MIPS_BRANCH ("b%F0", "%Z2%1")); | |
5085 } | |
5086 [(set_attr "type" "branch") | |
5087 (set_attr "mode" "none")]) | |
5088 | |
5089 ;; Conditional branches on ordered comparisons with zero. | |
5090 | |
5091 (define_insn "*branch_order<mode>" | |
5092 [(set (pc) | |
5093 (if_then_else | |
5094 (match_operator 0 "order_operator" | |
5095 [(match_operand:GPR 2 "register_operand" "d") | |
5096 (const_int 0)]) | |
5097 (label_ref (match_operand 1 "" "")) | |
5098 (pc)))] | |
5099 "!TARGET_MIPS16" | |
5100 { return mips_output_order_conditional_branch (insn, operands, false); } | |
5101 [(set_attr "type" "branch") | |
5102 (set_attr "mode" "none")]) | |
5103 | |
5104 (define_insn "*branch_order<mode>_inverted" | |
5105 [(set (pc) | |
5106 (if_then_else | |
5107 (match_operator 0 "order_operator" | |
5108 [(match_operand:GPR 2 "register_operand" "d") | |
5109 (const_int 0)]) | |
5110 (pc) | |
5111 (label_ref (match_operand 1 "" ""))))] | |
5112 "!TARGET_MIPS16" | |
5113 { return mips_output_order_conditional_branch (insn, operands, true); } | |
5114 [(set_attr "type" "branch") | |
5115 (set_attr "mode" "none")]) | |
5116 | |
5117 ;; Conditional branch on equality comparison. | |
5118 | |
5119 (define_insn "*branch_equality<mode>" | |
5120 [(set (pc) | |
5121 (if_then_else | |
5122 (match_operator 0 "equality_operator" | |
5123 [(match_operand:GPR 2 "register_operand" "d") | |
5124 (match_operand:GPR 3 "reg_or_0_operand" "dJ")]) | |
5125 (label_ref (match_operand 1 "" "")) | |
5126 (pc)))] | |
5127 "!TARGET_MIPS16" | |
5128 { | |
5129 return mips_output_conditional_branch (insn, operands, | |
5130 MIPS_BRANCH ("b%C0", "%2,%z3,%1"), | |
5131 MIPS_BRANCH ("b%N0", "%2,%z3,%1")); | |
5132 } | |
5133 [(set_attr "type" "branch") | |
5134 (set_attr "mode" "none")]) | |
5135 | |
5136 (define_insn "*branch_equality<mode>_inverted" | |
5137 [(set (pc) | |
5138 (if_then_else | |
5139 (match_operator 0 "equality_operator" | |
5140 [(match_operand:GPR 2 "register_operand" "d") | |
5141 (match_operand:GPR 3 "reg_or_0_operand" "dJ")]) | |
5142 (pc) | |
5143 (label_ref (match_operand 1 "" ""))))] | |
5144 "!TARGET_MIPS16" | |
5145 { | |
5146 return mips_output_conditional_branch (insn, operands, | |
5147 MIPS_BRANCH ("b%N0", "%2,%z3,%1"), | |
5148 MIPS_BRANCH ("b%C0", "%2,%z3,%1")); | |
5149 } | |
5150 [(set_attr "type" "branch") | |
5151 (set_attr "mode" "none")]) | |
5152 | |
5153 ;; MIPS16 branches | |
5154 | |
5155 (define_insn "*branch_equality<mode>_mips16" | |
5156 [(set (pc) | |
5157 (if_then_else | |
5158 (match_operator 0 "equality_operator" | |
5159 [(match_operand:GPR 1 "register_operand" "d,t") | |
5160 (const_int 0)]) | |
5161 (match_operand 2 "pc_or_label_operand" "") | |
5162 (match_operand 3 "pc_or_label_operand" "")))] | |
5163 "TARGET_MIPS16" | |
5164 { | |
5165 if (operands[2] != pc_rtx) | |
5166 { | |
5167 if (which_alternative == 0) | |
5168 return "b%C0z\t%1,%2"; | |
5169 else | |
5170 return "bt%C0z\t%2"; | |
5171 } | |
5172 else | |
5173 { | |
5174 if (which_alternative == 0) | |
5175 return "b%N0z\t%1,%3"; | |
5176 else | |
5177 return "bt%N0z\t%3"; | |
5178 } | |
5179 } | |
5180 [(set_attr "type" "branch") | |
5181 (set_attr "mode" "none")]) | |
5182 | |
5183 (define_expand "b<code>" | |
5184 [(set (pc) | |
5185 (if_then_else (any_cond:CC (cc0) | |
5186 (const_int 0)) | |
5187 (label_ref (match_operand 0 "")) | |
5188 (pc)))] | |
5189 "" | |
5190 { | |
5191 mips_expand_conditional_branch (operands, <CODE>); | |
5192 DONE; | |
5193 }) | |
5194 | |
5195 ;; Used to implement built-in functions. | |
5196 (define_expand "condjump" | |
5197 [(set (pc) | |
5198 (if_then_else (match_operand 0) | |
5199 (label_ref (match_operand 1)) | |
5200 (pc)))]) | |
5201 | |
5202 ;; Branch if bit is set/clear. | |
5203 | |
5204 (define_insn "*branch_bit<bbv><mode>" | |
5205 [(set (pc) | |
5206 (if_then_else | |
5207 (equality_op (zero_extract:GPR | |
5208 (match_operand:GPR 0 "register_operand" "d") | |
5209 (const_int 1) | |
5210 (match_operand 2 "const_int_operand" "")) | |
5211 (const_int 0)) | |
5212 (label_ref (match_operand 1 "")) | |
5213 (pc)))] | |
5214 "ISA_HAS_BBIT && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)" | |
5215 { | |
5216 return | |
5217 mips_output_conditional_branch (insn, operands, | |
5218 MIPS_BRANCH ("bbit<bbv>", "%0,%2,%1"), | |
5219 MIPS_BRANCH ("bbit<bbinv>", "%0,%2,%1")); | |
5220 } | |
5221 [(set_attr "type" "branch") | |
5222 (set_attr "mode" "none") | |
5223 (set_attr "branch_likely" "no")]) | |
5224 | |
5225 (define_insn "*branch_bit<bbv><mode>_inverted" | |
5226 [(set (pc) | |
5227 (if_then_else | |
5228 (equality_op (zero_extract:GPR | |
5229 (match_operand:GPR 0 "register_operand" "d") | |
5230 (const_int 1) | |
5231 (match_operand 2 "const_int_operand" "")) | |
5232 (const_int 0)) | |
5233 (pc) | |
5234 (label_ref (match_operand 1 ""))))] | |
5235 "ISA_HAS_BBIT && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)" | |
5236 { | |
5237 return | |
5238 mips_output_conditional_branch (insn, operands, | |
5239 MIPS_BRANCH ("bbit<bbinv>", "%0,%2,%1"), | |
5240 MIPS_BRANCH ("bbit<bbv>", "%0,%2,%1")); | |
5241 } | |
5242 [(set_attr "type" "branch") | |
5243 (set_attr "mode" "none") | |
5244 (set_attr "branch_likely" "no")]) | |
5245 | |
5246 ;; | |
5247 ;; .................... | |
5248 ;; | |
5249 ;; SETTING A REGISTER FROM A COMPARISON | |
5250 ;; | |
5251 ;; .................... | |
5252 | |
5253 ;; Destination is always set in SI mode. | |
5254 | |
5255 (define_expand "seq" | |
5256 [(set (match_operand:SI 0 "register_operand") | |
5257 (eq:SI (match_dup 1) | |
5258 (match_dup 2)))] | |
5259 "" | |
5260 { if (mips_expand_scc (EQ, operands[0])) DONE; else FAIL; }) | |
5261 | |
5262 (define_insn "*seq_zero_<GPR:mode><GPR2:mode>" | |
5263 [(set (match_operand:GPR2 0 "register_operand" "=d") | |
5264 (eq:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5265 (const_int 0)))] | |
5266 "!TARGET_MIPS16 && !ISA_HAS_SEQ_SNE" | |
5267 "sltu\t%0,%1,1" | |
5268 [(set_attr "type" "slt") | |
5269 (set_attr "mode" "<GPR:MODE>")]) | |
5270 | |
5271 (define_insn "*seq_zero_<GPR:mode><GPR2:mode>_mips16" | |
5272 [(set (match_operand:GPR2 0 "register_operand" "=t") | |
5273 (eq:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5274 (const_int 0)))] | |
5275 "TARGET_MIPS16 && !ISA_HAS_SEQ_SNE" | |
5276 "sltu\t%1,1" | |
5277 [(set_attr "type" "slt") | |
5278 (set_attr "mode" "<GPR:MODE>")]) | |
5279 | |
5280 ;; Generate sltiu unless using seq results in better code. | |
5281 (define_insn "*seq_<GPR:mode><GPR2:mode>_seq" | |
5282 [(set (match_operand:GPR2 0 "register_operand" "=d,d,d") | |
5283 (eq:GPR2 (match_operand:GPR 1 "register_operand" "%d,d,d") | |
5284 (match_operand:GPR 2 "reg_imm10_operand" "d,J,YB")))] | |
5285 "ISA_HAS_SEQ_SNE" | |
5286 "@ | |
5287 seq\t%0,%1,%2 | |
5288 sltiu\t%0,%1,1 | |
5289 seqi\t%0,%1,%2" | |
5290 [(set_attr "type" "slt") | |
5291 (set_attr "mode" "<GPR:MODE>")]) | |
5292 | |
5293 ;; "sne" uses sltu instructions in which the first operand is $0. | |
5294 ;; This isn't possible in mips16 code. | |
5295 | |
5296 (define_expand "sne" | |
5297 [(set (match_operand:SI 0 "register_operand") | |
5298 (ne:SI (match_dup 1) | |
5299 (match_dup 2)))] | |
5300 "!TARGET_MIPS16" | |
5301 { if (mips_expand_scc (NE, operands[0])) DONE; else FAIL; }) | |
5302 | |
5303 (define_insn "*sne_zero_<GPR:mode><GPR2:mode>" | |
5304 [(set (match_operand:GPR2 0 "register_operand" "=d") | |
5305 (ne:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5306 (const_int 0)))] | |
5307 "!TARGET_MIPS16 && !ISA_HAS_SEQ_SNE" | |
5308 "sltu\t%0,%.,%1" | |
5309 [(set_attr "type" "slt") | |
5310 (set_attr "mode" "<GPR:MODE>")]) | |
5311 | |
5312 ;; Generate sltu unless using sne results in better code. | |
5313 (define_insn "*sne_<GPR:mode><GPR2:mode>_sne" | |
5314 [(set (match_operand:GPR2 0 "register_operand" "=d,d,d") | |
5315 (ne:GPR2 (match_operand:GPR 1 "register_operand" "%d,d,d") | |
5316 (match_operand:GPR 2 "reg_imm10_operand" "d,J,YB")))] | |
5317 "ISA_HAS_SEQ_SNE" | |
5318 "@ | |
5319 sne\t%0,%1,%2 | |
5320 sltu\t%0,%.,%1 | |
5321 snei\t%0,%1,%2" | |
5322 [(set_attr "type" "slt") | |
5323 (set_attr "mode" "<GPR:MODE>")]) | |
5324 | |
5325 (define_expand "sgt<u>" | |
5326 [(set (match_operand:SI 0 "register_operand") | |
5327 (any_gt:SI (match_dup 1) | |
5328 (match_dup 2)))] | |
5329 "" | |
5330 { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; }) | |
5331 | |
5332 (define_insn "*sgt<u>_<GPR:mode><GPR2:mode>" | |
5333 [(set (match_operand:GPR2 0 "register_operand" "=d") | |
5334 (any_gt:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5335 (match_operand:GPR 2 "reg_or_0_operand" "dJ")))] | |
5336 "!TARGET_MIPS16" | |
5337 "slt<u>\t%0,%z2,%1" | |
5338 [(set_attr "type" "slt") | |
5339 (set_attr "mode" "<GPR:MODE>")]) | |
5340 | |
5341 (define_insn "*sgt<u>_<GPR:mode><GPR2:mode>_mips16" | |
5342 [(set (match_operand:GPR2 0 "register_operand" "=t") | |
5343 (any_gt:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5344 (match_operand:GPR 2 "register_operand" "d")))] | |
5345 "TARGET_MIPS16" | |
5346 "slt<u>\t%2,%1" | |
5347 [(set_attr "type" "slt") | |
5348 (set_attr "mode" "<GPR:MODE>")]) | |
5349 | |
5350 (define_expand "sge<u>" | |
5351 [(set (match_operand:SI 0 "register_operand") | |
5352 (any_ge:SI (match_dup 1) | |
5353 (match_dup 2)))] | |
5354 "" | |
5355 { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; }) | |
5356 | |
5357 (define_insn "*sge<u>_<GPR:mode><GPR2:mode>" | |
5358 [(set (match_operand:GPR2 0 "register_operand" "=d") | |
5359 (any_ge:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5360 (const_int 1)))] | |
5361 "!TARGET_MIPS16" | |
5362 "slt<u>\t%0,%.,%1" | |
5363 [(set_attr "type" "slt") | |
5364 (set_attr "mode" "<GPR:MODE>")]) | |
5365 | |
5366 (define_expand "slt<u>" | |
5367 [(set (match_operand:SI 0 "register_operand") | |
5368 (any_lt:SI (match_dup 1) | |
5369 (match_dup 2)))] | |
5370 "" | |
5371 { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; }) | |
5372 | |
5373 (define_insn "*slt<u>_<GPR:mode><GPR2:mode>" | |
5374 [(set (match_operand:GPR2 0 "register_operand" "=d") | |
5375 (any_lt:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5376 (match_operand:GPR 2 "arith_operand" "dI")))] | |
5377 "!TARGET_MIPS16" | |
5378 "slt<u>\t%0,%1,%2" | |
5379 [(set_attr "type" "slt") | |
5380 (set_attr "mode" "<GPR:MODE>")]) | |
5381 | |
5382 (define_insn "*slt<u>_<GPR:mode><GPR2:mode>_mips16" | |
5383 [(set (match_operand:GPR2 0 "register_operand" "=t,t") | |
5384 (any_lt:GPR2 (match_operand:GPR 1 "register_operand" "d,d") | |
5385 (match_operand:GPR 2 "arith_operand" "d,I")))] | |
5386 "TARGET_MIPS16" | |
5387 "slt<u>\t%1,%2" | |
5388 [(set_attr "type" "slt") | |
5389 (set_attr "mode" "<GPR:MODE>") | |
5390 (set_attr_alternative "length" | |
5391 [(const_int 4) | |
5392 (if_then_else (match_operand 2 "m16_uimm8_1") | |
5393 (const_int 4) | |
5394 (const_int 8))])]) | |
5395 | |
5396 (define_expand "sle<u>" | |
5397 [(set (match_operand:SI 0 "register_operand") | |
5398 (any_le:SI (match_dup 1) | |
5399 (match_dup 2)))] | |
5400 "" | |
5401 { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; }) | |
5402 | |
5403 (define_insn "*sle<u>_<GPR:mode><GPR2:mode>" | |
5404 [(set (match_operand:GPR2 0 "register_operand" "=d") | |
5405 (any_le:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5406 (match_operand:GPR 2 "sle_operand" "")))] | |
5407 "!TARGET_MIPS16" | |
5408 { | |
5409 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); | |
5410 return "slt<u>\t%0,%1,%2"; | |
5411 } | |
5412 [(set_attr "type" "slt") | |
5413 (set_attr "mode" "<GPR:MODE>")]) | |
5414 | |
5415 (define_insn "*sle<u>_<GPR:mode><GPR2:mode>_mips16" | |
5416 [(set (match_operand:GPR2 0 "register_operand" "=t") | |
5417 (any_le:GPR2 (match_operand:GPR 1 "register_operand" "d") | |
5418 (match_operand:GPR 2 "sle_operand" "")))] | |
5419 "TARGET_MIPS16" | |
5420 { | |
5421 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); | |
5422 return "slt<u>\t%1,%2"; | |
5423 } | |
5424 [(set_attr "type" "slt") | |
5425 (set_attr "mode" "<GPR:MODE>") | |
5426 (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1") | |
5427 (const_int 4) | |
5428 (const_int 8)))]) | |
5429 | |
5430 ;; | |
5431 ;; .................... | |
5432 ;; | |
5433 ;; FLOATING POINT COMPARISONS | |
5434 ;; | |
5435 ;; .................... | |
5436 | |
5437 (define_insn "s<code>_<mode>" | |
5438 [(set (match_operand:CC 0 "register_operand" "=z") | |
5439 (fcond:CC (match_operand:SCALARF 1 "register_operand" "f") | |
5440 (match_operand:SCALARF 2 "register_operand" "f")))] | |
5441 "" | |
5442 "c.<fcond>.<fmt>\t%Z0%1,%2" | |
5443 [(set_attr "type" "fcmp") | |
5444 (set_attr "mode" "FPSW")]) | |
5445 | |
5446 (define_insn "s<code>_<mode>" | |
5447 [(set (match_operand:CC 0 "register_operand" "=z") | |
5448 (swapped_fcond:CC (match_operand:SCALARF 1 "register_operand" "f") | |
5449 (match_operand:SCALARF 2 "register_operand" "f")))] | |
5450 "" | |
5451 "c.<swapped_fcond>.<fmt>\t%Z0%2,%1" | |
5452 [(set_attr "type" "fcmp") | |
5453 (set_attr "mode" "FPSW")]) | |
5454 | |
5455 ;; | |
5456 ;; .................... | |
5457 ;; | |
5458 ;; UNCONDITIONAL BRANCHES | |
5459 ;; | |
5460 ;; .................... | |
5461 | |
5462 ;; Unconditional branches. | |
5463 | |
5464 (define_insn "jump" | |
5465 [(set (pc) | |
5466 (label_ref (match_operand 0 "" "")))] | |
5467 "!TARGET_MIPS16" | |
5468 { | |
5469 if (flag_pic) | |
5470 { | |
5471 if (get_attr_length (insn) <= 8) | |
5472 return "%*b\t%l0%/"; | |
5473 else | |
5474 { | |
5475 output_asm_insn (mips_output_load_label (), operands); | |
5476 return "%*jr\t%@%/%]"; | |
5477 } | |
5478 } | |
5479 else | |
5480 return "%*j\t%l0%/"; | |
5481 } | |
5482 [(set_attr "type" "jump") | |
5483 (set_attr "mode" "none") | |
5484 (set (attr "length") | |
5485 ;; We can't use `j' when emitting PIC. Emit a branch if it's | |
5486 ;; in range, otherwise load the address of the branch target into | |
5487 ;; $at and then jump to it. | |
5488 (if_then_else | |
5489 (ior (eq (symbol_ref "flag_pic") (const_int 0)) | |
5490 (lt (abs (minus (match_dup 0) | |
5491 (plus (pc) (const_int 4)))) | |
5492 (const_int 131072))) | |
5493 (const_int 4) (const_int 16)))]) | |
5494 | |
5495 ;; We need a different insn for the mips16, because a mips16 branch | |
5496 ;; does not have a delay slot. | |
5497 | |
5498 (define_insn "" | |
5499 [(set (pc) | |
5500 (label_ref (match_operand 0 "" "")))] | |
5501 "TARGET_MIPS16" | |
5502 "b\t%l0" | |
5503 [(set_attr "type" "branch") | |
5504 (set_attr "mode" "none")]) | |
5505 | |
5506 (define_expand "indirect_jump" | |
5507 [(set (pc) (match_operand 0 "register_operand"))] | |
5508 "" | |
5509 { | |
5510 operands[0] = force_reg (Pmode, operands[0]); | |
5511 if (Pmode == SImode) | |
5512 emit_jump_insn (gen_indirect_jumpsi (operands[0])); | |
5513 else | |
5514 emit_jump_insn (gen_indirect_jumpdi (operands[0])); | |
5515 DONE; | |
5516 }) | |
5517 | |
5518 (define_insn "indirect_jump<mode>" | |
5519 [(set (pc) (match_operand:P 0 "register_operand" "d"))] | |
5520 "" | |
5521 "%*j\t%0%/" | |
5522 [(set_attr "type" "jump") | |
5523 (set_attr "mode" "none")]) | |
5524 | |
5525 (define_expand "tablejump" | |
5526 [(set (pc) | |
5527 (match_operand 0 "register_operand")) | |
5528 (use (label_ref (match_operand 1 "")))] | |
5529 "" | |
5530 { | |
5531 if (TARGET_MIPS16_SHORT_JUMP_TABLES) | |
5532 operands[0] = expand_binop (Pmode, add_optab, | |
5533 convert_to_mode (Pmode, operands[0], false), | |
5534 gen_rtx_LABEL_REF (Pmode, operands[1]), | |
5535 0, 0, OPTAB_WIDEN); | |
5536 else if (TARGET_GPWORD) | |
5537 operands[0] = expand_binop (Pmode, add_optab, operands[0], | |
5538 pic_offset_table_rtx, 0, 0, OPTAB_WIDEN); | |
5539 else if (TARGET_RTP_PIC) | |
5540 { | |
5541 /* When generating RTP PIC, we use case table entries that are relative | |
5542 to the start of the function. Add the function's address to the | |
5543 value we loaded. */ | |
5544 rtx start = get_hard_reg_initial_val (Pmode, PIC_FUNCTION_ADDR_REGNUM); | |
5545 operands[0] = expand_binop (ptr_mode, add_optab, operands[0], | |
5546 start, 0, 0, OPTAB_WIDEN); | |
5547 } | |
5548 | |
5549 if (Pmode == SImode) | |
5550 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); | |
5551 else | |
5552 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); | |
5553 DONE; | |
5554 }) | |
5555 | |
5556 (define_insn "tablejump<mode>" | |
5557 [(set (pc) | |
5558 (match_operand:P 0 "register_operand" "d")) | |
5559 (use (label_ref (match_operand 1 "" "")))] | |
5560 "" | |
5561 "%*j\t%0%/" | |
5562 [(set_attr "type" "jump") | |
5563 (set_attr "mode" "none")]) | |
5564 | |
5565 ;; For TARGET_USE_GOT, we save the gp in the jmp_buf as well. | |
5566 ;; While it is possible to either pull it off the stack (in the | |
5567 ;; o32 case) or recalculate it given t9 and our target label, | |
5568 ;; it takes 3 or 4 insns to do so. | |
5569 | |
5570 (define_expand "builtin_setjmp_setup" | |
5571 [(use (match_operand 0 "register_operand"))] | |
5572 "TARGET_USE_GOT" | |
5573 { | |
5574 rtx addr; | |
5575 | |
5576 addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3); | |
5577 mips_emit_move (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx); | |
5578 DONE; | |
5579 }) | |
5580 | |
5581 ;; Restore the gp that we saved above. Despite the earlier comment, it seems | |
5582 ;; that older code did recalculate the gp from $25. Continue to jump through | |
5583 ;; $25 for compatibility (we lose nothing by doing so). | |
5584 | |
5585 (define_expand "builtin_longjmp" | |
5586 [(use (match_operand 0 "register_operand"))] | |
5587 "TARGET_USE_GOT" | |
5588 { | |
5589 /* The elements of the buffer are, in order: */ | |
5590 int W = GET_MODE_SIZE (Pmode); | |
5591 rtx fp = gen_rtx_MEM (Pmode, operands[0]); | |
5592 rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W)); | |
5593 rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W)); | |
5594 rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W)); | |
5595 rtx pv = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM); | |
5596 /* Use gen_raw_REG to avoid being given pic_offset_table_rtx. | |
5597 The target is bound to be using $28 as the global pointer | |
5598 but the current function might not be. */ | |
5599 rtx gp = gen_raw_REG (Pmode, GLOBAL_POINTER_REGNUM); | |
5600 | |
5601 /* This bit is similar to expand_builtin_longjmp except that it | |
5602 restores $gp as well. */ | |
5603 mips_emit_move (hard_frame_pointer_rtx, fp); | |
5604 mips_emit_move (pv, lab); | |
5605 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); | |
5606 mips_emit_move (gp, gpv); | |
5607 emit_use (hard_frame_pointer_rtx); | |
5608 emit_use (stack_pointer_rtx); | |
5609 emit_use (gp); | |
5610 emit_indirect_jump (pv); | |
5611 DONE; | |
5612 }) | |
5613 | |
5614 ;; | |
5615 ;; .................... | |
5616 ;; | |
5617 ;; Function prologue/epilogue | |
5618 ;; | |
5619 ;; .................... | |
5620 ;; | |
5621 | |
5622 (define_expand "prologue" | |
5623 [(const_int 1)] | |
5624 "" | |
5625 { | |
5626 mips_expand_prologue (); | |
5627 DONE; | |
5628 }) | |
5629 | |
5630 ;; Block any insns from being moved before this point, since the | |
5631 ;; profiling call to mcount can use various registers that aren't | |
5632 ;; saved or used to pass arguments. | |
5633 | |
5634 (define_insn "blockage" | |
5635 [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)] | |
5636 "" | |
5637 "" | |
5638 [(set_attr "type" "ghost") | |
5639 (set_attr "mode" "none")]) | |
5640 | |
5641 (define_expand "epilogue" | |
5642 [(const_int 2)] | |
5643 "" | |
5644 { | |
5645 mips_expand_epilogue (false); | |
5646 DONE; | |
5647 }) | |
5648 | |
5649 (define_expand "sibcall_epilogue" | |
5650 [(const_int 2)] | |
5651 "" | |
5652 { | |
5653 mips_expand_epilogue (true); | |
5654 DONE; | |
5655 }) | |
5656 | |
5657 ;; Trivial return. Make it look like a normal return insn as that | |
5658 ;; allows jump optimizations to work better. | |
5659 | |
5660 (define_expand "return" | |
5661 [(return)] | |
5662 "mips_can_use_return_insn ()" | |
5663 { mips_expand_before_return (); }) | |
5664 | |
5665 (define_insn "*return" | |
5666 [(return)] | |
5667 "mips_can_use_return_insn ()" | |
5668 "%*j\t$31%/" | |
5669 [(set_attr "type" "jump") | |
5670 (set_attr "mode" "none")]) | |
5671 | |
5672 ;; Normal return. | |
5673 | |
5674 (define_insn "return_internal" | |
5675 [(return) | |
5676 (use (match_operand 0 "pmode_register_operand" ""))] | |
5677 "" | |
5678 "%*j\t%0%/" | |
5679 [(set_attr "type" "jump") | |
5680 (set_attr "mode" "none")]) | |
5681 | |
5682 ;; This is used in compiling the unwind routines. | |
5683 (define_expand "eh_return" | |
5684 [(use (match_operand 0 "general_operand"))] | |
5685 "" | |
5686 { | |
5687 if (GET_MODE (operands[0]) != word_mode) | |
5688 operands[0] = convert_to_mode (word_mode, operands[0], 0); | |
5689 if (TARGET_64BIT) | |
5690 emit_insn (gen_eh_set_lr_di (operands[0])); | |
5691 else | |
5692 emit_insn (gen_eh_set_lr_si (operands[0])); | |
5693 DONE; | |
5694 }) | |
5695 | |
5696 ;; Clobber the return address on the stack. We can't expand this | |
5697 ;; until we know where it will be put in the stack frame. | |
5698 | |
5699 (define_insn "eh_set_lr_si" | |
5700 [(unspec [(match_operand:SI 0 "register_operand" "d")] UNSPEC_EH_RETURN) | |
5701 (clobber (match_scratch:SI 1 "=&d"))] | |
5702 "! TARGET_64BIT" | |
5703 "#") | |
5704 | |
5705 (define_insn "eh_set_lr_di" | |
5706 [(unspec [(match_operand:DI 0 "register_operand" "d")] UNSPEC_EH_RETURN) | |
5707 (clobber (match_scratch:DI 1 "=&d"))] | |
5708 "TARGET_64BIT" | |
5709 "#") | |
5710 | |
5711 (define_split | |
5712 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN) | |
5713 (clobber (match_scratch 1))] | |
5714 "reload_completed" | |
5715 [(const_int 0)] | |
5716 { | |
5717 mips_set_return_address (operands[0], operands[1]); | |
5718 DONE; | |
5719 }) | |
5720 | |
5721 (define_expand "exception_receiver" | |
5722 [(const_int 0)] | |
5723 "TARGET_USE_GOT" | |
5724 { | |
5725 /* See the comment above load_call<mode> for details. */ | |
5726 emit_insn (gen_set_got_version ()); | |
5727 | |
5728 /* If we have a call-clobbered $gp, restore it from its save slot. */ | |
5729 if (HAVE_restore_gp) | |
5730 emit_insn (gen_restore_gp ()); | |
5731 DONE; | |
5732 }) | |
5733 | |
5734 (define_expand "nonlocal_goto_receiver" | |
5735 [(const_int 0)] | |
5736 "TARGET_USE_GOT" | |
5737 { | |
5738 /* See the comment above load_call<mode> for details. */ | |
5739 emit_insn (gen_set_got_version ()); | |
5740 DONE; | |
5741 }) | |
5742 | |
5743 ;; Restore $gp from its .cprestore stack slot. The instruction remains | |
5744 ;; volatile until all uses of $28 are exposed. | |
5745 (define_insn_and_split "restore_gp" | |
5746 [(set (reg:SI 28) | |
5747 (unspec_volatile:SI [(const_int 0)] UNSPEC_RESTORE_GP)) | |
5748 (clobber (match_scratch:SI 0 "=&d"))] | |
5749 "TARGET_CALL_CLOBBERED_GP" | |
5750 "#" | |
5751 "&& reload_completed" | |
5752 [(const_int 0)] | |
5753 { | |
5754 mips_restore_gp (operands[0]); | |
5755 DONE; | |
5756 } | |
5757 [(set_attr "type" "load") | |
5758 (set_attr "length" "12")]) | |
5759 | |
5760 ;; | |
5761 ;; .................... | |
5762 ;; | |
5763 ;; FUNCTION CALLS | |
5764 ;; | |
5765 ;; .................... | |
5766 | |
5767 ;; Instructions to load a call address from the GOT. The address might | |
5768 ;; point to a function or to a lazy binding stub. In the latter case, | |
5769 ;; the stub will use the dynamic linker to resolve the function, which | |
5770 ;; in turn will change the GOT entry to point to the function's real | |
5771 ;; address. | |
5772 ;; | |
5773 ;; This means that every call, even pure and constant ones, can | |
5774 ;; potentially modify the GOT entry. And once a stub has been called, | |
5775 ;; we must not call it again. | |
5776 ;; | |
5777 ;; We represent this restriction using an imaginary, fixed, call-saved | |
5778 ;; register called GOT_VERSION_REGNUM. The idea is to make the register | |
5779 ;; live throughout the function and to change its value after every | |
5780 ;; potential call site. This stops any rtx value that uses the register | |
5781 ;; from being computed before an earlier call. To do this, we: | |
5782 ;; | |
5783 ;; - Ensure that the register is live on entry to the function, | |
5784 ;; so that it is never thought to be used uninitalized. | |
5785 ;; | |
5786 ;; - Ensure that the register is live on exit from the function, | |
5787 ;; so that it is live throughout. | |
5788 ;; | |
5789 ;; - Make each call (lazily-bound or not) use the current value | |
5790 ;; of GOT_VERSION_REGNUM, so that updates of the register are | |
5791 ;; not moved across call boundaries. | |
5792 ;; | |
5793 ;; - Add "ghost" definitions of the register to the beginning of | |
5794 ;; blocks reached by EH and ABNORMAL_CALL edges, because those | |
5795 ;; edges may involve calls that normal paths don't. (E.g. the | |
5796 ;; unwinding code that handles a non-call exception may change | |
5797 ;; lazily-bound GOT entries.) We do this by making the | |
5798 ;; exception_receiver and nonlocal_goto_receiver expanders emit | |
5799 ;; a set_got_version instruction. | |
5800 ;; | |
5801 ;; - After each call (lazily-bound or not), use a "ghost" | |
5802 ;; update_got_version instruction to change the register's value. | |
5803 ;; This instruction mimics the _possible_ effect of the dynamic | |
5804 ;; resolver during the call and it remains live even if the call | |
5805 ;; itself becomes dead. | |
5806 ;; | |
5807 ;; - Leave GOT_VERSION_REGNUM out of all register classes. | |
5808 ;; The register is therefore not a valid register_operand | |
5809 ;; and cannot be moved to or from other registers. | |
5810 | |
5811 ;; Convenience expander that generates the rhs of a load_call<mode> insn. | |
5812 (define_expand "unspec_call<mode>" | |
5813 [(unspec:P [(match_operand:P 0) | |
5814 (match_operand:P 1) | |
5815 (reg:SI GOT_VERSION_REGNUM)] UNSPEC_LOAD_CALL)]) | |
5816 | |
5817 (define_insn "load_call<mode>" | |
5818 [(set (match_operand:P 0 "register_operand" "=d") | |
5819 (unspec:P [(match_operand:P 1 "register_operand" "d") | |
5820 (match_operand:P 2 "immediate_operand" "") | |
5821 (reg:SI GOT_VERSION_REGNUM)] UNSPEC_LOAD_CALL))] | |
5822 "TARGET_USE_GOT" | |
5823 "<load>\t%0,%R2(%1)" | |
5824 [(set_attr "got" "load") | |
5825 (set_attr "mode" "<MODE>")]) | |
5826 | |
5827 (define_insn "set_got_version" | |
5828 [(set (reg:SI GOT_VERSION_REGNUM) | |
5829 (unspec_volatile:SI [(const_int 0)] UNSPEC_SET_GOT_VERSION))] | |
5830 "TARGET_USE_GOT" | |
5831 "" | |
5832 [(set_attr "type" "ghost")]) | |
5833 | |
5834 (define_insn "update_got_version" | |
5835 [(set (reg:SI GOT_VERSION_REGNUM) | |
5836 (unspec:SI [(reg:SI GOT_VERSION_REGNUM)] UNSPEC_UPDATE_GOT_VERSION))] | |
5837 "TARGET_USE_GOT" | |
5838 "" | |
5839 [(set_attr "type" "ghost")]) | |
5840 | |
5841 ;; Sibling calls. All these patterns use jump instructions. | |
5842 | |
5843 ;; If TARGET_SIBCALLS, call_insn_operand will only accept constant | |
5844 ;; addresses if a direct jump is acceptable. Since the 'S' constraint | |
5845 ;; is defined in terms of call_insn_operand, the same is true of the | |
5846 ;; constraints. | |
5847 | |
5848 ;; When we use an indirect jump, we need a register that will be | |
5849 ;; preserved by the epilogue. Since TARGET_USE_PIC_FN_ADDR_REG forces | |
5850 ;; us to use $25 for this purpose -- and $25 is never clobbered by the | |
5851 ;; epilogue -- we might as well use it for !TARGET_USE_PIC_FN_ADDR_REG | |
5852 ;; as well. | |
5853 | |
5854 (define_expand "sibcall" | |
5855 [(parallel [(call (match_operand 0 "") | |
5856 (match_operand 1 "")) | |
5857 (use (match_operand 2 "")) ;; next_arg_reg | |
5858 (use (match_operand 3 ""))])] ;; struct_value_size_rtx | |
5859 "TARGET_SIBCALLS" | |
5860 { | |
5861 mips_expand_call (MIPS_CALL_SIBCALL, NULL_RTX, XEXP (operands[0], 0), | |
5862 operands[1], operands[2], false); | |
5863 DONE; | |
5864 }) | |
5865 | |
5866 (define_insn "sibcall_internal" | |
5867 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S")) | |
5868 (match_operand 1 "" ""))] | |
5869 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" | |
5870 { return MIPS_CALL ("j", operands, 0); } | |
5871 [(set_attr "type" "call")]) | |
5872 | |
5873 (define_expand "sibcall_value" | |
5874 [(parallel [(set (match_operand 0 "") | |
5875 (call (match_operand 1 "") | |
5876 (match_operand 2 ""))) | |
5877 (use (match_operand 3 ""))])] ;; next_arg_reg | |
5878 "TARGET_SIBCALLS" | |
5879 { | |
5880 mips_expand_call (MIPS_CALL_SIBCALL, operands[0], XEXP (operands[1], 0), | |
5881 operands[2], operands[3], false); | |
5882 DONE; | |
5883 }) | |
5884 | |
5885 (define_insn "sibcall_value_internal" | |
5886 [(set (match_operand 0 "register_operand" "") | |
5887 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) | |
5888 (match_operand 2 "" "")))] | |
5889 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" | |
5890 { return MIPS_CALL ("j", operands, 1); } | |
5891 [(set_attr "type" "call")]) | |
5892 | |
5893 (define_insn "sibcall_value_multiple_internal" | |
5894 [(set (match_operand 0 "register_operand" "") | |
5895 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) | |
5896 (match_operand 2 "" ""))) | |
5897 (set (match_operand 3 "register_operand" "") | |
5898 (call (mem:SI (match_dup 1)) | |
5899 (match_dup 2)))] | |
5900 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" | |
5901 { return MIPS_CALL ("j", operands, 1); } | |
5902 [(set_attr "type" "call")]) | |
5903 | |
5904 (define_expand "call" | |
5905 [(parallel [(call (match_operand 0 "") | |
5906 (match_operand 1 "")) | |
5907 (use (match_operand 2 "")) ;; next_arg_reg | |
5908 (use (match_operand 3 ""))])] ;; struct_value_size_rtx | |
5909 "" | |
5910 { | |
5911 mips_expand_call (MIPS_CALL_NORMAL, NULL_RTX, XEXP (operands[0], 0), | |
5912 operands[1], operands[2], false); | |
5913 DONE; | |
5914 }) | |
5915 | |
5916 ;; This instruction directly corresponds to an assembly-language "jal". | |
5917 ;; There are four cases: | |
5918 ;; | |
5919 ;; - -mno-abicalls: | |
5920 ;; Both symbolic and register destinations are OK. The pattern | |
5921 ;; always expands to a single mips instruction. | |
5922 ;; | |
5923 ;; - -mabicalls/-mno-explicit-relocs: | |
5924 ;; Again, both symbolic and register destinations are OK. | |
5925 ;; The call is treated as a multi-instruction black box. | |
5926 ;; | |
5927 ;; - -mabicalls/-mexplicit-relocs with n32 or n64: | |
5928 ;; Only "jal $25" is allowed. This expands to a single "jalr $25" | |
5929 ;; instruction. | |
5930 ;; | |
5931 ;; - -mabicalls/-mexplicit-relocs with o32 or o64: | |
5932 ;; Only "jal $25" is allowed. The call is actually two instructions: | |
5933 ;; "jalr $25" followed by an insn to reload $gp. | |
5934 ;; | |
5935 ;; In the last case, we can generate the individual instructions with | |
5936 ;; a define_split. There are several things to be wary of: | |
5937 ;; | |
5938 ;; - We can't expose the load of $gp before reload. If we did, | |
5939 ;; it might get removed as dead, but reload can introduce new | |
5940 ;; uses of $gp by rematerializing constants. | |
5941 ;; | |
5942 ;; - We shouldn't restore $gp after calls that never return. | |
5943 ;; It isn't valid to insert instructions between a noreturn | |
5944 ;; call and the following barrier. | |
5945 ;; | |
5946 ;; - The splitter deliberately changes the liveness of $gp. The unsplit | |
5947 ;; instruction preserves $gp and so have no effect on its liveness. | |
5948 ;; But once we generate the separate insns, it becomes obvious that | |
5949 ;; $gp is not live on entry to the call. | |
5950 ;; | |
5951 ;; ??? The operands[2] = insn check is a hack to make the original insn | |
5952 ;; available to the splitter. | |
5953 (define_insn_and_split "call_internal" | |
5954 [(call (mem:SI (match_operand 0 "call_insn_operand" "c,S")) | |
5955 (match_operand 1 "" "")) | |
5956 (clobber (reg:SI 31))] | |
5957 "" | |
5958 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0); } | |
5959 "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)" | |
5960 [(const_int 0)] | |
5961 { | |
5962 mips_split_call (operands[2], gen_call_split (operands[0], operands[1])); | |
5963 DONE; | |
5964 } | |
5965 [(set_attr "jal" "indirect,direct")]) | |
5966 | |
5967 (define_insn "call_split" | |
5968 [(call (mem:SI (match_operand 0 "call_insn_operand" "cS")) | |
5969 (match_operand 1 "" "")) | |
5970 (clobber (reg:SI 31)) | |
5971 (clobber (reg:SI 28))] | |
5972 "TARGET_SPLIT_CALLS" | |
5973 { return MIPS_CALL ("jal", operands, 0); } | |
5974 [(set_attr "type" "call")]) | |
5975 | |
5976 ;; A pattern for calls that must be made directly. It is used for | |
5977 ;; MIPS16 calls that the linker may need to redirect to a hard-float | |
5978 ;; stub; the linker relies on the call relocation type to detect when | |
5979 ;; such redirection is needed. | |
5980 (define_insn_and_split "call_internal_direct" | |
5981 [(call (mem:SI (match_operand 0 "const_call_insn_operand")) | |
5982 (match_operand 1)) | |
5983 (const_int 1) | |
5984 (clobber (reg:SI 31))] | |
5985 "" | |
5986 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0); } | |
5987 "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)" | |
5988 [(const_int 0)] | |
5989 { | |
5990 mips_split_call (operands[2], | |
5991 gen_call_direct_split (operands[0], operands[1])); | |
5992 DONE; | |
5993 } | |
5994 [(set_attr "type" "call")]) | |
5995 | |
5996 (define_insn "call_direct_split" | |
5997 [(call (mem:SI (match_operand 0 "const_call_insn_operand")) | |
5998 (match_operand 1)) | |
5999 (const_int 1) | |
6000 (clobber (reg:SI 31)) | |
6001 (clobber (reg:SI 28))] | |
6002 "TARGET_SPLIT_CALLS" | |
6003 { return MIPS_CALL ("jal", operands, 0); } | |
6004 [(set_attr "type" "call")]) | |
6005 | |
6006 (define_expand "call_value" | |
6007 [(parallel [(set (match_operand 0 "") | |
6008 (call (match_operand 1 "") | |
6009 (match_operand 2 ""))) | |
6010 (use (match_operand 3 ""))])] ;; next_arg_reg | |
6011 "" | |
6012 { | |
6013 mips_expand_call (MIPS_CALL_NORMAL, operands[0], XEXP (operands[1], 0), | |
6014 operands[2], operands[3], false); | |
6015 DONE; | |
6016 }) | |
6017 | |
6018 ;; See comment for call_internal. | |
6019 (define_insn_and_split "call_value_internal" | |
6020 [(set (match_operand 0 "register_operand" "") | |
6021 (call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) | |
6022 (match_operand 2 "" ""))) | |
6023 (clobber (reg:SI 31))] | |
6024 "" | |
6025 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); } | |
6026 "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)" | |
6027 [(const_int 0)] | |
6028 { | |
6029 mips_split_call (operands[3], | |
6030 gen_call_value_split (operands[0], operands[1], | |
6031 operands[2])); | |
6032 DONE; | |
6033 } | |
6034 [(set_attr "jal" "indirect,direct")]) | |
6035 | |
6036 (define_insn "call_value_split" | |
6037 [(set (match_operand 0 "register_operand" "") | |
6038 (call (mem:SI (match_operand 1 "call_insn_operand" "cS")) | |
6039 (match_operand 2 "" ""))) | |
6040 (clobber (reg:SI 31)) | |
6041 (clobber (reg:SI 28))] | |
6042 "TARGET_SPLIT_CALLS" | |
6043 { return MIPS_CALL ("jal", operands, 1); } | |
6044 [(set_attr "type" "call")]) | |
6045 | |
6046 ;; See call_internal_direct. | |
6047 (define_insn_and_split "call_value_internal_direct" | |
6048 [(set (match_operand 0 "register_operand") | |
6049 (call (mem:SI (match_operand 1 "const_call_insn_operand")) | |
6050 (match_operand 2))) | |
6051 (const_int 1) | |
6052 (clobber (reg:SI 31))] | |
6053 "" | |
6054 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); } | |
6055 "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)" | |
6056 [(const_int 0)] | |
6057 { | |
6058 mips_split_call (operands[3], | |
6059 gen_call_value_direct_split (operands[0], operands[1], | |
6060 operands[2])); | |
6061 DONE; | |
6062 } | |
6063 [(set_attr "type" "call")]) | |
6064 | |
6065 (define_insn "call_value_direct_split" | |
6066 [(set (match_operand 0 "register_operand") | |
6067 (call (mem:SI (match_operand 1 "const_call_insn_operand")) | |
6068 (match_operand 2))) | |
6069 (const_int 1) | |
6070 (clobber (reg:SI 31)) | |
6071 (clobber (reg:SI 28))] | |
6072 "TARGET_SPLIT_CALLS" | |
6073 { return MIPS_CALL ("jal", operands, 1); } | |
6074 [(set_attr "type" "call")]) | |
6075 | |
6076 ;; See comment for call_internal. | |
6077 (define_insn_and_split "call_value_multiple_internal" | |
6078 [(set (match_operand 0 "register_operand" "") | |
6079 (call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) | |
6080 (match_operand 2 "" ""))) | |
6081 (set (match_operand 3 "register_operand" "") | |
6082 (call (mem:SI (match_dup 1)) | |
6083 (match_dup 2))) | |
6084 (clobber (reg:SI 31))] | |
6085 "" | |
6086 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); } | |
6087 "reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)" | |
6088 [(const_int 0)] | |
6089 { | |
6090 mips_split_call (operands[4], | |
6091 gen_call_value_multiple_split (operands[0], operands[1], | |
6092 operands[2], operands[3])); | |
6093 DONE; | |
6094 } | |
6095 [(set_attr "jal" "indirect,direct")]) | |
6096 | |
6097 (define_insn "call_value_multiple_split" | |
6098 [(set (match_operand 0 "register_operand" "") | |
6099 (call (mem:SI (match_operand 1 "call_insn_operand" "cS")) | |
6100 (match_operand 2 "" ""))) | |
6101 (set (match_operand 3 "register_operand" "") | |
6102 (call (mem:SI (match_dup 1)) | |
6103 (match_dup 2))) | |
6104 (clobber (reg:SI 31)) | |
6105 (clobber (reg:SI 28))] | |
6106 "TARGET_SPLIT_CALLS" | |
6107 { return MIPS_CALL ("jal", operands, 1); } | |
6108 [(set_attr "type" "call")]) | |
6109 | |
6110 ;; Call subroutine returning any type. | |
6111 | |
6112 (define_expand "untyped_call" | |
6113 [(parallel [(call (match_operand 0 "") | |
6114 (const_int 0)) | |
6115 (match_operand 1 "") | |
6116 (match_operand 2 "")])] | |
6117 "" | |
6118 { | |
6119 int i; | |
6120 | |
6121 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); | |
6122 | |
6123 for (i = 0; i < XVECLEN (operands[2], 0); i++) | |
6124 { | |
6125 rtx set = XVECEXP (operands[2], 0, i); | |
6126 mips_emit_move (SET_DEST (set), SET_SRC (set)); | |
6127 } | |
6128 | |
6129 emit_insn (gen_blockage ()); | |
6130 DONE; | |
6131 }) | |
6132 | |
6133 ;; | |
6134 ;; .................... | |
6135 ;; | |
6136 ;; MISC. | |
6137 ;; | |
6138 ;; .................... | |
6139 ;; | |
6140 | |
6141 | |
6142 (define_insn "prefetch" | |
6143 [(prefetch (match_operand:QI 0 "address_operand" "p") | |
6144 (match_operand 1 "const_int_operand" "n") | |
6145 (match_operand 2 "const_int_operand" "n"))] | |
6146 "ISA_HAS_PREFETCH && TARGET_EXPLICIT_RELOCS" | |
6147 { | |
6148 if (TARGET_LOONGSON_2EF) | |
6149 /* Loongson 2[ef] use load to $0 to perform prefetching. */ | |
6150 return "ld\t$0,%a0"; | |
6151 operands[1] = mips_prefetch_cookie (operands[1], operands[2]); | |
6152 return "pref\t%1,%a0"; | |
6153 } | |
6154 [(set_attr "type" "prefetch")]) | |
6155 | |
6156 (define_insn "*prefetch_indexed_<mode>" | |
6157 [(prefetch (plus:P (match_operand:P 0 "register_operand" "d") | |
6158 (match_operand:P 1 "register_operand" "d")) | |
6159 (match_operand 2 "const_int_operand" "n") | |
6160 (match_operand 3 "const_int_operand" "n"))] | |
6161 "ISA_HAS_PREFETCHX && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" | |
6162 { | |
6163 operands[2] = mips_prefetch_cookie (operands[2], operands[3]); | |
6164 return "prefx\t%2,%1(%0)"; | |
6165 } | |
6166 [(set_attr "type" "prefetchx")]) | |
6167 | |
6168 (define_insn "nop" | |
6169 [(const_int 0)] | |
6170 "" | |
6171 "%(nop%)" | |
6172 [(set_attr "type" "nop") | |
6173 (set_attr "mode" "none")]) | |
6174 | |
6175 ;; Like nop, but commented out when outside a .set noreorder block. | |
6176 (define_insn "hazard_nop" | |
6177 [(const_int 1)] | |
6178 "" | |
6179 { | |
6180 if (set_noreorder) | |
6181 return "nop"; | |
6182 else | |
6183 return "#nop"; | |
6184 } | |
6185 [(set_attr "type" "nop")]) | |
6186 | |
6187 ;; MIPS4 Conditional move instructions. | |
6188 | |
6189 (define_insn "*mov<GPR:mode>_on_<MOVECC:mode>" | |
6190 [(set (match_operand:GPR 0 "register_operand" "=d,d") | |
6191 (if_then_else:GPR | |
6192 (match_operator:MOVECC 4 "equality_operator" | |
6193 [(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>") | |
6194 (const_int 0)]) | |
6195 (match_operand:GPR 2 "reg_or_0_operand" "dJ,0") | |
6196 (match_operand:GPR 3 "reg_or_0_operand" "0,dJ")))] | |
6197 "ISA_HAS_CONDMOVE" | |
6198 "@ | |
6199 mov%T4\t%0,%z2,%1 | |
6200 mov%t4\t%0,%z3,%1" | |
6201 [(set_attr "type" "condmove") | |
6202 (set_attr "mode" "<GPR:MODE>")]) | |
6203 | |
6204 (define_insn "*mov<SCALARF:mode>_on_<MOVECC:mode>" | |
6205 [(set (match_operand:SCALARF 0 "register_operand" "=f,f") | |
6206 (if_then_else:SCALARF | |
6207 (match_operator:MOVECC 4 "equality_operator" | |
6208 [(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>") | |
6209 (const_int 0)]) | |
6210 (match_operand:SCALARF 2 "register_operand" "f,0") | |
6211 (match_operand:SCALARF 3 "register_operand" "0,f")))] | |
6212 "ISA_HAS_FP_CONDMOVE" | |
6213 "@ | |
6214 mov%T4.<fmt>\t%0,%2,%1 | |
6215 mov%t4.<fmt>\t%0,%3,%1" | |
6216 [(set_attr "type" "condmove") | |
6217 (set_attr "mode" "<SCALARF:MODE>")]) | |
6218 | |
6219 ;; These are the main define_expand's used to make conditional moves. | |
6220 | |
6221 (define_expand "mov<mode>cc" | |
6222 [(set (match_dup 4) (match_operand 1 "comparison_operator")) | |
6223 (set (match_operand:GPR 0 "register_operand") | |
6224 (if_then_else:GPR (match_dup 5) | |
6225 (match_operand:GPR 2 "reg_or_0_operand") | |
6226 (match_operand:GPR 3 "reg_or_0_operand")))] | |
6227 "ISA_HAS_CONDMOVE" | |
6228 { | |
6229 mips_expand_conditional_move (operands); | |
6230 DONE; | |
6231 }) | |
6232 | |
6233 (define_expand "mov<mode>cc" | |
6234 [(set (match_dup 4) (match_operand 1 "comparison_operator")) | |
6235 (set (match_operand:SCALARF 0 "register_operand") | |
6236 (if_then_else:SCALARF (match_dup 5) | |
6237 (match_operand:SCALARF 2 "register_operand") | |
6238 (match_operand:SCALARF 3 "register_operand")))] | |
6239 "ISA_HAS_FP_CONDMOVE" | |
6240 { | |
6241 mips_expand_conditional_move (operands); | |
6242 DONE; | |
6243 }) | |
6244 | |
6245 ;; | |
6246 ;; .................... | |
6247 ;; | |
6248 ;; mips16 inline constant tables | |
6249 ;; | |
6250 ;; .................... | |
6251 ;; | |
6252 | |
6253 (define_insn "consttable_int" | |
6254 [(unspec_volatile [(match_operand 0 "consttable_operand" "") | |
6255 (match_operand 1 "const_int_operand" "")] | |
6256 UNSPEC_CONSTTABLE_INT)] | |
6257 "TARGET_MIPS16" | |
6258 { | |
6259 assemble_integer (operands[0], INTVAL (operands[1]), | |
6260 BITS_PER_UNIT * INTVAL (operands[1]), 1); | |
6261 return ""; | |
6262 } | |
6263 [(set (attr "length") (symbol_ref "INTVAL (operands[1])"))]) | |
6264 | |
6265 (define_insn "consttable_float" | |
6266 [(unspec_volatile [(match_operand 0 "consttable_operand" "")] | |
6267 UNSPEC_CONSTTABLE_FLOAT)] | |
6268 "TARGET_MIPS16" | |
6269 { | |
6270 REAL_VALUE_TYPE d; | |
6271 | |
6272 gcc_assert (GET_CODE (operands[0]) == CONST_DOUBLE); | |
6273 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); | |
6274 assemble_real (d, GET_MODE (operands[0]), | |
6275 GET_MODE_BITSIZE (GET_MODE (operands[0]))); | |
6276 return ""; | |
6277 } | |
6278 [(set (attr "length") | |
6279 (symbol_ref "GET_MODE_SIZE (GET_MODE (operands[0]))"))]) | |
6280 | |
6281 (define_insn "align" | |
6282 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPEC_ALIGN)] | |
6283 "" | |
6284 ".align\t%0" | |
6285 [(set (attr "length") (symbol_ref "(1 << INTVAL (operands[0])) - 1"))]) | |
6286 | |
6287 (define_split | |
6288 [(match_operand 0 "small_data_pattern")] | |
6289 "reload_completed" | |
6290 [(match_dup 0)] | |
6291 { operands[0] = mips_rewrite_small_data (operands[0]); }) | |
6292 | |
6293 ;; | |
6294 ;; .................... | |
6295 ;; | |
6296 ;; MIPS16e Save/Restore | |
6297 ;; | |
6298 ;; .................... | |
6299 ;; | |
6300 | |
6301 (define_insn "*mips16e_save_restore" | |
6302 [(match_parallel 0 "" | |
6303 [(set (match_operand:SI 1 "register_operand") | |
6304 (plus:SI (match_dup 1) | |
6305 (match_operand:SI 2 "const_int_operand")))])] | |
6306 "operands[1] == stack_pointer_rtx | |
6307 && mips16e_save_restore_pattern_p (operands[0], INTVAL (operands[2]), NULL)" | |
6308 { return mips16e_output_save_restore (operands[0], INTVAL (operands[2])); } | |
6309 [(set_attr "type" "arith") | |
6310 (set_attr "extended_mips16" "yes")]) | |
6311 | |
6312 ;; Thread-Local Storage | |
6313 | |
6314 ;; The TLS base pointer is accessed via "rdhwr $3, $29". No current | |
6315 ;; MIPS architecture defines this register, and no current | |
6316 ;; implementation provides it; instead, any OS which supports TLS is | |
6317 ;; expected to trap and emulate this instruction. rdhwr is part of the | |
6318 ;; MIPS 32r2 specification, but we use it on any architecture because | |
6319 ;; we expect it to be emulated. Use .set to force the assembler to | |
6320 ;; accept it. | |
6321 ;; | |
6322 ;; We do not use a constraint to force the destination to be $3 | |
6323 ;; because $3 can appear explicitly as a function return value. | |
6324 ;; If we leave the use of $3 implicit in the constraints until | |
6325 ;; reload, we may end up making a $3 return value live across | |
6326 ;; the instruction, leading to a spill failure when reloading it. | |
6327 (define_insn_and_split "tls_get_tp_<mode>" | |
6328 [(set (match_operand:P 0 "register_operand" "=d") | |
6329 (unspec:P [(const_int 0)] UNSPEC_TLS_GET_TP)) | |
6330 (clobber (reg:P TLS_GET_TP_REGNUM))] | |
6331 "HAVE_AS_TLS && !TARGET_MIPS16" | |
6332 "#" | |
6333 "&& reload_completed" | |
6334 [(set (reg:P TLS_GET_TP_REGNUM) | |
6335 (unspec:P [(const_int 0)] UNSPEC_TLS_GET_TP)) | |
6336 (set (match_dup 0) (reg:P TLS_GET_TP_REGNUM))] | |
6337 "" | |
6338 [(set_attr "type" "unknown") | |
6339 ; Since rdhwr always generates a trap for now, putting it in a delay | |
6340 ; slot would make the kernel's emulation of it much slower. | |
6341 (set_attr "can_delay" "no") | |
6342 (set_attr "mode" "<MODE>") | |
6343 (set_attr "length" "8")]) | |
6344 | |
6345 (define_insn "*tls_get_tp_<mode>_split" | |
6346 [(set (reg:P TLS_GET_TP_REGNUM) | |
6347 (unspec:P [(const_int 0)] UNSPEC_TLS_GET_TP))] | |
6348 "HAVE_AS_TLS && !TARGET_MIPS16" | |
6349 ".set\tpush\;.set\tmips32r2\t\;rdhwr\t$3,$29\;.set\tpop" | |
6350 [(set_attr "type" "unknown") | |
6351 ; See tls_get_tp_<mode> | |
6352 (set_attr "can_delay" "no") | |
6353 (set_attr "mode" "<MODE>")]) | |
6354 | |
6355 ;; Synchronization instructions. | |
6356 | |
6357 (include "sync.md") | |
6358 | |
6359 ; The MIPS Paired-Single Floating Point and MIPS-3D Instructions. | |
6360 | |
6361 (include "mips-ps-3d.md") | |
6362 | |
6363 ; The MIPS DSP Instructions. | |
6364 | |
6365 (include "mips-dsp.md") | |
6366 | |
6367 ; The MIPS DSP REV 2 Instructions. | |
6368 | |
6369 (include "mips-dspr2.md") | |
6370 | |
6371 ; MIPS fixed-point instructions. | |
6372 (include "mips-fixed.md") | |
6373 | |
6374 ; ST-Microelectronics Loongson-2E/2F-specific patterns. | |
6375 (include "loongson.md") |