]>
Commit | Line | Data |
---|---|---|
8ef30996 | 1 | ;; Mips.md Machine Description for MIPS based processors |
214be03f JL |
2 | ;; Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, |
3 | ;; 1999, 2000 Free Software Foundation, Inc. | |
8ef30996 MM |
4 | ;; Contributed by A. Lichnewsky, lich@inria.inria.fr |
5 | ;; Changes by Michael Meissner, meissner@osf.org | |
bb621ad7 JW |
6 | ;; 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and |
7 | ;; Brendan Eich, brendan@microunity.com. | |
8ef30996 MM |
8 | |
9 | ;; This file is part of GNU CC. | |
10 | ||
11 | ;; GNU CC is free software; you can redistribute it and/or modify | |
12 | ;; it under the terms of the GNU General Public License as published by | |
13 | ;; the Free Software Foundation; either version 2, or (at your option) | |
14 | ;; any later version. | |
15 | ||
16 | ;; GNU CC is distributed in the hope that it will be useful, | |
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;; GNU General Public License for more details. | |
20 | ||
21 | ;; You should have received a copy of the GNU General Public License | |
22 | ;; along with GNU CC; see the file COPYING. If not, write to | |
3f63df56 RK |
23 | ;; the Free Software Foundation, 59 Temple Place - Suite 330, |
24 | ;; Boston, MA 02111-1307, USA. | |
8ef30996 | 25 | |
e19ff60f JW |
26 | ;; ??? Currently does not have define_function_unit support for the R8000. |
27 | ;; Must include new entries for fmadd in addition to existing entries. | |
28 | ||
8ef30996 MM |
29 | \f |
30 | ||
31 | ;; .................... | |
32 | ;; | |
33 | ;; Attributes | |
34 | ;; | |
35 | ;; .................... | |
36 | ||
37 | ;; Classification of each insn. | |
38 | ;; branch conditional branch | |
39 | ;; jump unconditional jump | |
40 | ;; call unconditional call | |
41 | ;; load load instruction(s) | |
42 | ;; store store instruction(s) | |
43 | ;; move data movement within same register set | |
44 | ;; xfer transfer to/from coprocessor | |
45 | ;; hilo transfer of hi/lo registers | |
46 | ;; arith integer arithmetic instruction | |
47 | ;; darith double precision integer arithmetic instructions | |
48 | ;; imul integer multiply | |
49 | ;; idiv integer divide | |
50 | ;; icmp integer compare | |
51 | ;; fadd floating point add/subtract | |
52 | ;; fmul floating point multiply | |
e19ff60f | 53 | ;; fmadd floating point multiply-add |
8ef30996 MM |
54 | ;; fdiv floating point divide |
55 | ;; fabs floating point absolute value | |
56 | ;; fneg floating point negation | |
57 | ;; fcmp floating point compare | |
58 | ;; fcvt floating point convert | |
59 | ;; fsqrt floating point square root | |
60 | ;; multi multiword sequence (or user asm statements) | |
61 | ;; nop no operation | |
8ef30996 MM |
62 | |
63 | (define_attr "type" | |
e19ff60f | 64 | "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop" |
8ef30996 MM |
65 | (const_string "unknown")) |
66 | ||
67 | ;; Main data type used by the insn | |
34b650b3 | 68 | (define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown")) |
8ef30996 | 69 | |
0ff83799 MM |
70 | ;; Length (in # of bytes). A conditional branch is allowed only to a |
71 | ;; location within a signed 18-bit offset of the delay slot. If that | |
72 | ;; provides too smal a range, we use the `j' instruction. This | |
73 | ;; instruction takes a 28-bit value, but that value is not an offset. | |
74 | ;; Instead, it's bitwise-ored with the high-order four bits of the | |
75 | ;; instruction in the delay slot, which means it cannot be used to | |
76 | ;; cross a 256MB boundary. We could fall back back on the jr, | |
77 | ;; instruction which allows full access to the entire address space, | |
78 | ;; but we do not do so at present. | |
79 | ||
80 | (define_attr "length" "" | |
81 | (cond [(eq_attr "type" "branch") | |
82 | (cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 4)))) | |
83 | (const_int 131072)) | |
84 | (const_int 4)] | |
85 | (const_int 12))] | |
86 | (const_int 4))) | |
8ef30996 | 87 | |
ddd8ab48 MM |
88 | ;; Attribute describing the processor. This attribute must match exactly |
89 | ;; with the processor_type enumeration in mips.h. | |
90 | ||
8ef30996 | 91 | ;; Attribute describing the processor |
ddd8ab48 MM |
92 | ;; (define_attr "cpu" "default,r3000,r6000,r4000" |
93 | ;; (const | |
94 | ;; (cond [(eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R3000")) (const_string "r3000") | |
95 | ;; (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R4000")) (const_string "r4000") | |
96 | ;; (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R6000")) (const_string "r6000")] | |
97 | ;; (const_string "default")))) | |
98 | ||
e19ff60f | 99 | ;; ??? Fix everything that tests this attribute. |
b8eb88d0 | 100 | (define_attr "cpu" |
e9a25f70 | 101 | "default,r3000,r3900,r6000,r4000,r4100,r4300,r4600,r4650,r5000,r8000" |
ddd8ab48 | 102 | (const (symbol_ref "mips_cpu_attr"))) |
8ef30996 | 103 | |
ec350bdd | 104 | ;; Does the instruction have a mandatory delay slot? |
0ff83799 | 105 | ;; The 3900, is (mostly) mips1, but does not have a mandatory load delay |
ec350bdd GK |
106 | ;; slot. |
107 | (define_attr "dslot" "no,yes" | |
108 | (if_then_else (ior (eq_attr "type" "branch,jump,call,xfer,hilo,fcmp") | |
109 | (and (eq_attr "type" "load") | |
110 | (and (eq (symbol_ref "mips_isa") (const_int 1)) | |
111 | (and (eq (symbol_ref "mips16") (const_int 0)) | |
112 | (eq_attr "cpu" "!r3900"))))) | |
113 | (const_string "yes") | |
114 | (const_string "no"))) | |
115 | ||
8ef30996 | 116 | ;; Attribute defining whether or not we can use the branch-likely instructions |
8ef30996 MM |
117 | |
118 | (define_attr "branch_likely" "no,yes" | |
6d518002 | 119 | (const |
e9a25f70 | 120 | (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0)) |
8ef30996 | 121 | (const_string "yes") |
6d518002 | 122 | (const_string "no")))) |
8ef30996 MM |
123 | |
124 | ||
125 | ;; Describe a user's asm statement. | |
126 | (define_asm_attributes | |
127 | [(set_attr "type" "multi")]) | |
128 | ||
84a92af4 JW |
129 | ;; whether or not generating calls to position independent functions |
130 | (define_attr "abicalls" "no,yes" | |
e0a4e5a5 | 131 | (const (symbol_ref "mips_abicalls_attr"))) |
84a92af4 | 132 | |
8ef30996 MM |
133 | \f |
134 | ||
135 | ;; ......................... | |
136 | ;; | |
137 | ;; Delay slots, can't describe load/fcmp/xfer delay slots here | |
138 | ;; | |
139 | ;; ......................... | |
140 | ||
2bcb2ab3 GK |
141 | (define_delay (and (eq_attr "type" "branch") |
142 | (eq (symbol_ref "mips16") (const_int 0))) | |
0ff83799 | 143 | [(and (eq_attr "dslot" "no") (eq_attr "length" "4")) |
8ef30996 | 144 | (nil) |
0ff83799 | 145 | (and (eq_attr "branch_likely" "yes") (and (eq_attr "dslot" "no") (eq_attr "length" "4")))]) |
8ef30996 | 146 | |
84a92af4 | 147 | (define_delay (eq_attr "type" "jump") |
0ff83799 | 148 | [(and (eq_attr "dslot" "no") (eq_attr "length" "4")) |
84a92af4 JW |
149 | (nil) |
150 | (nil)]) | |
151 | ||
152 | (define_delay (and (eq_attr "type" "call") (eq_attr "abicalls" "no")) | |
0ff83799 | 153 | [(and (eq_attr "dslot" "no") (eq_attr "length" "4")) |
8ef30996 MM |
154 | (nil) |
155 | (nil)]) | |
156 | ||
157 | \f | |
158 | ||
159 | ;; ......................... | |
160 | ;; | |
161 | ;; Functional units | |
162 | ;; | |
163 | ;; ......................... | |
164 | ||
165 | ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY | |
c8e18a2b | 166 | ; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) |
8ef30996 MM |
167 | |
168 | ;; Make the default case (PROCESSOR_DEFAULT) handle the worst case | |
169 | ||
170 | (define_function_unit "memory" 1 0 | |
b8eb88d0 | 171 | (and (eq_attr "type" "load") |
e9a25f70 | 172 | (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4100,r4300,r5000")) |
8ef30996 MM |
173 | 3 0) |
174 | ||
175 | (define_function_unit "memory" 1 0 | |
b8eb88d0 | 176 | (and (eq_attr "type" "load") |
e9a25f70 | 177 | (eq_attr "cpu" "r3000,r3900,r4600,r4650,r4100,r4300,r5000")) |
8ef30996 MM |
178 | 2 0) |
179 | ||
ddd8ab48 | 180 | (define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) |
8ef30996 | 181 | |
c3f3d7e1 | 182 | (define_function_unit "memory" 1 0 (eq_attr "type" "xfer") 2 0) |
8ef30996 | 183 | |
bb621ad7 JW |
184 | (define_function_unit "imuldiv" 1 0 |
185 | (eq_attr "type" "hilo") | |
186 | 1 3) | |
187 | ||
188 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 | 189 | (and (eq_attr "type" "imul") |
e9a25f70 | 190 | (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000")) |
bb621ad7 | 191 | 17 17) |
8ef30996 | 192 | |
2bcb2ab3 GK |
193 | ;; On them mips16, we want to stronly discourage a mult from appearing |
194 | ;; after an mflo, since that requires explicit nop instructions. We | |
195 | ;; do this by pretending that mflo ties up the function unit for long | |
196 | ;; enough that the scheduler will ignore load stalls and the like when | |
197 | ;; selecting instructions to between the two instructions. | |
198 | ||
199 | (define_function_unit "imuldiv" 1 0 | |
200 | (and (eq_attr "type" "hilo") (ne (symbol_ref "mips16") (const_int 0))) | |
201 | 1 5) | |
202 | ||
bb621ad7 | 203 | (define_function_unit "imuldiv" 1 0 |
e9a25f70 | 204 | (and (eq_attr "type" "imul") (eq_attr "cpu" "r3000,r3900")) |
bb621ad7 | 205 | 12 12) |
8ef30996 | 206 | |
bb621ad7 JW |
207 | (define_function_unit "imuldiv" 1 0 |
208 | (and (eq_attr "type" "imul") (eq_attr "cpu" "r4000,r4600")) | |
209 | 10 10) | |
8ef30996 | 210 | |
bb621ad7 | 211 | (define_function_unit "imuldiv" 1 0 |
053665d7 ILT |
212 | (and (eq_attr "type" "imul") (eq_attr "cpu" "r4650")) |
213 | 4 4) | |
214 | ||
215 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 ILT |
216 | (and (eq_attr "type" "imul") |
217 | (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100"))) | |
8fbaea49 JW |
218 | 1 1) |
219 | ||
220 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 ILT |
221 | (and (eq_attr "type" "imul") |
222 | (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100"))) | |
8fbaea49 JW |
223 | 4 4) |
224 | ||
225 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 ILT |
226 | (and (eq_attr "type" "imul") |
227 | (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300,r5000"))) | |
8fbaea49 JW |
228 | 5 5) |
229 | ||
230 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 ILT |
231 | (and (eq_attr "type" "imul") |
232 | (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300"))) | |
8fbaea49 JW |
233 | 8 8) |
234 | ||
235 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 ILT |
236 | (and (eq_attr "type" "imul") |
237 | (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000"))) | |
238 | 9 9) | |
239 | ||
240 | (define_function_unit "imuldiv" 1 0 | |
241 | (and (eq_attr "type" "idiv") | |
e9a25f70 | 242 | (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000")) |
bb621ad7 | 243 | 38 38) |
8ef30996 | 244 | |
bb621ad7 | 245 | (define_function_unit "imuldiv" 1 0 |
e9a25f70 | 246 | (and (eq_attr "type" "idiv") (eq_attr "cpu" "r3000,r3900")) |
bb621ad7 JW |
247 | 35 35) |
248 | ||
249 | (define_function_unit "imuldiv" 1 0 | |
250 | (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4600")) | |
251 | 42 42) | |
8ef30996 | 252 | |
053665d7 ILT |
253 | (define_function_unit "imuldiv" 1 0 |
254 | (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4650")) | |
255 | 36 36) | |
256 | ||
bb621ad7 | 257 | (define_function_unit "imuldiv" 1 0 |
8ef30996 | 258 | (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4000")) |
bb621ad7 JW |
259 | 69 69) |
260 | ||
8fbaea49 | 261 | (define_function_unit "imuldiv" 1 0 |
b8eb88d0 ILT |
262 | (and (eq_attr "type" "idiv") |
263 | (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100"))) | |
8fbaea49 JW |
264 | 35 35) |
265 | ||
266 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 ILT |
267 | (and (eq_attr "type" "idiv") |
268 | (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100"))) | |
8fbaea49 JW |
269 | 67 67) |
270 | ||
271 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 ILT |
272 | (and (eq_attr "type" "idiv") |
273 | (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300"))) | |
8fbaea49 JW |
274 | 37 37) |
275 | ||
276 | (define_function_unit "imuldiv" 1 0 | |
b8eb88d0 ILT |
277 | (and (eq_attr "type" "idiv") |
278 | (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300"))) | |
8fbaea49 JW |
279 | 69 69) |
280 | ||
b8eb88d0 ILT |
281 | (define_function_unit "imuldiv" 1 0 |
282 | (and (eq_attr "type" "idiv") | |
283 | (and (eq_attr "mode" "SI") (eq_attr "cpu" "r5000"))) | |
284 | 36 36) | |
285 | ||
286 | (define_function_unit "imuldiv" 1 0 | |
287 | (and (eq_attr "type" "idiv") | |
288 | (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000"))) | |
289 | 68 68) | |
290 | ||
956d6950 | 291 | ;; The R4300 does *NOT* have a separate Floating Point Unit, instead |
8fbaea49 JW |
292 | ;; the FP hardware is part of the normal ALU circuitry. This means FP |
293 | ;; instructions affect the pipe-line, and no functional unit | |
294 | ;; parallelism can occur on R4300 processors. To force GCC into coding | |
295 | ;; for only a single functional unit, we force the R4300 FP | |
296 | ;; instructions to be processed in the "imuldiv" unit. | |
297 | ||
bb621ad7 | 298 | (define_function_unit "adder" 1 1 |
e9a25f70 | 299 | (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000")) |
bb621ad7 JW |
300 | 3 0) |
301 | ||
302 | (define_function_unit "adder" 1 1 | |
e9a25f70 | 303 | (and (eq_attr "type" "fcmp") (eq_attr "cpu" "r3000,r3900,r6000")) |
bb621ad7 | 304 | 2 0) |
8ef30996 | 305 | |
b8eb88d0 ILT |
306 | (define_function_unit "adder" 1 1 |
307 | (and (eq_attr "type" "fcmp") (eq_attr "cpu" "r5000")) | |
308 | 1 0) | |
309 | ||
8ef30996 | 310 | (define_function_unit "adder" 1 1 |
e9a25f70 | 311 | (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r3900,r6000,r4300")) |
c8e18a2b | 312 | 4 0) |
8ef30996 MM |
313 | |
314 | (define_function_unit "adder" 1 1 | |
e9a25f70 | 315 | (and (eq_attr "type" "fadd") (eq_attr "cpu" "r3000,r3900")) |
c8e18a2b | 316 | 2 0) |
8ef30996 MM |
317 | |
318 | (define_function_unit "adder" 1 1 | |
319 | (and (eq_attr "type" "fadd") (eq_attr "cpu" "r6000")) | |
c8e18a2b | 320 | 3 0) |
8ef30996 | 321 | |
ddd8ab48 | 322 | (define_function_unit "adder" 1 1 |
b8eb88d0 | 323 | (and (eq_attr "type" "fabs,fneg") |
e9a25f70 | 324 | (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4300,r5000")) |
c8e18a2b | 325 | 2 0) |
8ef30996 | 326 | |
ddd8ab48 | 327 | (define_function_unit "adder" 1 1 |
e9a25f70 | 328 | (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000,r3900,r4600,r4650,r5000")) |
c8e18a2b | 329 | 1 0) |
8ef30996 MM |
330 | |
331 | (define_function_unit "mult" 1 1 | |
b8eb88d0 ILT |
332 | (and (eq_attr "type" "fmul") |
333 | (and (eq_attr "mode" "SF") | |
e9a25f70 | 334 | (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000"))) |
c8e18a2b | 335 | 7 0) |
8ef30996 MM |
336 | |
337 | (define_function_unit "mult" 1 1 | |
b8eb88d0 | 338 | (and (eq_attr "type" "fmul") |
e9a25f70 | 339 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000,r3900,r5000"))) |
c8e18a2b | 340 | 4 0) |
8ef30996 MM |
341 | |
342 | (define_function_unit "mult" 1 1 | |
b8eb88d0 ILT |
343 | (and (eq_attr "type" "fmul") |
344 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) | |
c8e18a2b | 345 | 5 0) |
8ef30996 | 346 | |
bb621ad7 | 347 | (define_function_unit "mult" 1 1 |
b8eb88d0 ILT |
348 | (and (eq_attr "type" "fmul") |
349 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650"))) | |
bb621ad7 JW |
350 | 8 0) |
351 | ||
8ef30996 | 352 | (define_function_unit "mult" 1 1 |
b8eb88d0 | 353 | (and (eq_attr "type" "fmul") |
e9a25f70 | 354 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000"))) |
c8e18a2b | 355 | 8 0) |
8ef30996 MM |
356 | |
357 | (define_function_unit "mult" 1 1 | |
b8eb88d0 | 358 | (and (eq_attr "type" "fmul") |
e9a25f70 | 359 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000,r3900,r5000"))) |
c8e18a2b | 360 | 5 0) |
8ef30996 MM |
361 | |
362 | (define_function_unit "mult" 1 1 | |
b8eb88d0 ILT |
363 | (and (eq_attr "type" "fmul") |
364 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) | |
c8e18a2b | 365 | 6 0) |
8ef30996 MM |
366 | |
367 | (define_function_unit "divide" 1 1 | |
b8eb88d0 ILT |
368 | (and (eq_attr "type" "fdiv") |
369 | (and (eq_attr "mode" "SF") | |
e9a25f70 | 370 | (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000"))) |
c8e18a2b | 371 | 23 0) |
8ef30996 MM |
372 | |
373 | (define_function_unit "divide" 1 1 | |
b8eb88d0 | 374 | (and (eq_attr "type" "fdiv") |
e9a25f70 | 375 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000,r3900"))) |
c8e18a2b | 376 | 12 0) |
8ef30996 MM |
377 | |
378 | (define_function_unit "divide" 1 1 | |
b8eb88d0 ILT |
379 | (and (eq_attr "type" "fdiv") |
380 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) | |
c8e18a2b | 381 | 15 0) |
8ef30996 MM |
382 | |
383 | (define_function_unit "divide" 1 1 | |
b8eb88d0 ILT |
384 | (and (eq_attr "type" "fdiv") |
385 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650"))) | |
bb621ad7 JW |
386 | 32 0) |
387 | ||
388 | (define_function_unit "divide" 1 1 | |
b8eb88d0 ILT |
389 | (and (eq_attr "type" "fdiv") |
390 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000"))) | |
391 | 21 0) | |
392 | ||
393 | (define_function_unit "divide" 1 1 | |
394 | (and (eq_attr "type" "fdiv") | |
395 | (and (eq_attr "mode" "DF") | |
e9a25f70 | 396 | (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300"))) |
c8e18a2b | 397 | 36 0) |
8ef30996 MM |
398 | |
399 | (define_function_unit "divide" 1 1 | |
b8eb88d0 | 400 | (and (eq_attr "type" "fdiv") |
e9a25f70 | 401 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000,r3900"))) |
c8e18a2b | 402 | 19 0) |
8ef30996 MM |
403 | |
404 | (define_function_unit "divide" 1 1 | |
b8eb88d0 ILT |
405 | (and (eq_attr "type" "fdiv") |
406 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) | |
c8e18a2b | 407 | 16 0) |
8ef30996 | 408 | |
bb621ad7 | 409 | (define_function_unit "divide" 1 1 |
b8eb88d0 ILT |
410 | (and (eq_attr "type" "fdiv") |
411 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650"))) | |
bb621ad7 JW |
412 | 61 0) |
413 | ||
414 | ;;; ??? Is this number right? | |
415 | (define_function_unit "divide" 1 1 | |
b8eb88d0 ILT |
416 | (and (eq_attr "type" "fsqrt") |
417 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000"))) | |
bb621ad7 | 418 | 54 0) |
b8eb88d0 | 419 | |
bb621ad7 | 420 | (define_function_unit "divide" 1 1 |
b8eb88d0 ILT |
421 | (and (eq_attr "type" "fsqrt") |
422 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650"))) | |
bb621ad7 JW |
423 | 31 0) |
424 | ||
b8eb88d0 ILT |
425 | (define_function_unit "divide" 1 1 |
426 | (and (eq_attr "type" "fsqrt") | |
427 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000"))) | |
428 | 21 0) | |
429 | ||
bb621ad7 JW |
430 | ;;; ??? Is this number right? |
431 | (define_function_unit "divide" 1 1 | |
b8eb88d0 ILT |
432 | (and (eq_attr "type" "fsqrt") |
433 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000"))) | |
bb621ad7 | 434 | 112 0) |
b8eb88d0 | 435 | |
bb621ad7 | 436 | (define_function_unit "divide" 1 1 |
b8eb88d0 ILT |
437 | (and (eq_attr "type" "fsqrt") |
438 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650"))) | |
bb621ad7 | 439 | 60 0) |
8ef30996 | 440 | |
b8eb88d0 ILT |
441 | (define_function_unit "divide" 1 1 |
442 | (and (eq_attr "type" "fsqrt") | |
443 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "r5000"))) | |
444 | 36 0) | |
445 | ||
8fbaea49 JW |
446 | ;; R4300 FP instruction classes treated as part of the "imuldiv" |
447 | ;; functional unit: | |
448 | ||
449 | (define_function_unit "imuldiv" 1 0 | |
450 | (and (eq_attr "type" "fadd") (eq_attr "cpu" "r4300")) | |
451 | 3 3) | |
452 | ||
aa4e54c4 JW |
453 | (define_function_unit "imuldiv" 1 0 |
454 | (and (eq_attr "type" "fcmp,fabs,fneg") (eq_attr "cpu" "r4300")) | |
455 | 1 1) | |
456 | ||
8fbaea49 JW |
457 | (define_function_unit "imuldiv" 1 0 |
458 | (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300"))) | |
459 | 5 5) | |
460 | (define_function_unit "imuldiv" 1 0 | |
461 | (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300"))) | |
462 | 8 8) | |
463 | ||
464 | (define_function_unit "imuldiv" 1 0 | |
465 | (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt")) | |
466 | (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300"))) | |
467 | 29 29) | |
468 | (define_function_unit "imuldiv" 1 0 | |
469 | (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt")) | |
470 | (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300"))) | |
471 | 58 58) | |
ddd8ab48 MM |
472 | \f |
473 | ;; The following functional units do not use the cpu type, and use | |
474 | ;; much less memory in genattrtab.c. | |
475 | ||
c8e18a2b TW |
476 | ;; (define_function_unit "memory" 1 0 (eq_attr "type" "load") 3 0) |
477 | ;; (define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) | |
ddd8ab48 | 478 | ;; |
c8e18a2b | 479 | ;; (define_function_unit "fp_comp" 1 0 (eq_attr "type" "fcmp") 2 0) |
ddd8ab48 | 480 | ;; |
c8e18a2b TW |
481 | ;; (define_function_unit "transfer" 1 0 (eq_attr "type" "xfer") 2 0) |
482 | ;; (define_function_unit "transfer" 1 0 (eq_attr "type" "hilo") 3 0) | |
ddd8ab48 | 483 | ;; |
c8e18a2b TW |
484 | ;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "imul") 17 0) |
485 | ;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "idiv") 38 0) | |
ddd8ab48 | 486 | ;; |
c8e18a2b TW |
487 | ;; (define_function_unit "adder" 1 1 (eq_attr "type" "fadd") 4 0) |
488 | ;; (define_function_unit "adder" 1 1 (eq_attr "type" "fabs,fneg") 2 0) | |
ddd8ab48 | 489 | ;; |
c8e18a2b TW |
490 | ;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "SF")) 7 0) |
491 | ;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "DF")) 8 0) | |
ddd8ab48 | 492 | ;; |
c8e18a2b TW |
493 | ;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "SF")) 23 0) |
494 | ;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "DF")) 36 0) | |
ddd8ab48 | 495 | ;; |
c8e18a2b TW |
496 | ;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 0) |
497 | ;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 0) | |
a0b6cdee GM |
498 | \f |
499 | ;; | |
500 | ;; .................... | |
501 | ;; | |
502 | ;; CONDITIONAL TRAPS | |
503 | ;; | |
504 | ;; .................... | |
505 | ;; | |
ddd8ab48 | 506 | |
a0b6cdee GM |
507 | (define_insn "trap" |
508 | [(trap_if (const_int 1) (const_int 0))] | |
509 | "" | |
510 | "* | |
511 | { | |
512 | if (ISA_HAS_COND_TRAP) | |
513 | return \"teq\\t$0,$0\"; | |
514 | else | |
515 | return \"break\"; | |
516 | }") | |
517 | ||
518 | (define_expand "conditional_trap" | |
519 | [(trap_if (match_operator 0 "cmp_op" | |
520 | [(match_dup 2) (match_dup 3)]) | |
521 | (match_operand 1 "const_int_operand" ""))] | |
522 | "ISA_HAS_COND_TRAP" | |
523 | " | |
524 | { | |
525 | mips_gen_conditional_trap (operands); | |
526 | DONE; | |
527 | }") | |
528 | ||
529 | ;; Match a TRAP_IF with 2nd arg of 0. The div_trap_* insns match a | |
530 | ;; 2nd arg of any CONST_INT, so this insn must appear first. | |
531 | ;; gen_div_trap always generates TRAP_IF with 2nd arg of 6 or 7. | |
532 | ||
533 | (define_insn "" | |
534 | [(trap_if (match_operator 0 "trap_cmp_op" | |
535 | [(match_operand:SI 1 "reg_or_0_operand" "d") | |
536 | (match_operand:SI 2 "nonmemory_operand" "dI")]) | |
537 | (const_int 0))] | |
538 | "ISA_HAS_COND_TRAP" | |
539 | "t%C0\\t%z1,%z2") | |
8ef30996 MM |
540 | \f |
541 | ;; | |
542 | ;; .................... | |
543 | ;; | |
544 | ;; ADDITION | |
545 | ;; | |
546 | ;; .................... | |
547 | ;; | |
548 | ||
549 | (define_insn "adddf3" | |
550 | [(set (match_operand:DF 0 "register_operand" "=f") | |
551 | (plus:DF (match_operand:DF 1 "register_operand" "f") | |
552 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 553 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
554 | "add.d\\t%0,%1,%2" |
555 | [(set_attr "type" "fadd") | |
0ff83799 | 556 | (set_attr "mode" "DF")]) |
8ef30996 MM |
557 | |
558 | (define_insn "addsf3" | |
559 | [(set (match_operand:SF 0 "register_operand" "=f") | |
560 | (plus:SF (match_operand:SF 1 "register_operand" "f") | |
561 | (match_operand:SF 2 "register_operand" "f")))] | |
562 | "TARGET_HARD_FLOAT" | |
563 | "add.s\\t%0,%1,%2" | |
564 | [(set_attr "type" "fadd") | |
0ff83799 | 565 | (set_attr "mode" "SF")]) |
8ef30996 | 566 | |
71cd5224 | 567 | (define_expand "addsi3" |
8ef30996 | 568 | [(set (match_operand:SI 0 "register_operand" "=d") |
71cd5224 | 569 | (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") |
8ef30996 MM |
570 | (match_operand:SI 2 "arith_operand" "dI")))] |
571 | "" | |
71cd5224 RS |
572 | " |
573 | { | |
2bcb2ab3 GK |
574 | /* The mips16 assembler handles -32768 correctly, and so does gas, |
575 | but some other MIPS assemblers think that -32768 needs to be | |
576 | loaded into a register before it can be added in. */ | |
577 | if (! TARGET_MIPS16 | |
578 | && ! TARGET_GAS | |
579 | && GET_CODE (operands[2]) == CONST_INT | |
580 | && INTVAL (operands[2]) == -32768) | |
71cd5224 RS |
581 | operands[2] = force_reg (SImode, operands[2]); |
582 | }") | |
583 | ||
584 | (define_insn "addsi3_internal" | |
585 | [(set (match_operand:SI 0 "register_operand" "=d") | |
586 | (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") | |
587 | (match_operand:SI 2 "arith_operand" "dI")))] | |
2bcb2ab3 GK |
588 | "! TARGET_MIPS16 |
589 | && (TARGET_GAS | |
590 | || GET_CODE (operands[2]) != CONST_INT | |
591 | || INTVAL (operands[2]) != -32768)" | |
9b190d1c | 592 | "addu\\t%0,%z1,%2" |
8ef30996 | 593 | [(set_attr "type" "arith") |
0ff83799 | 594 | (set_attr "mode" "SI")]) |
8ef30996 | 595 | |
2bcb2ab3 GK |
596 | ;; For the mips16, we need to recognize stack pointer additions |
597 | ;; explicitly, since we don't have a constraint for $sp. These insns | |
598 | ;; will be generated by the save_restore_insns functions. | |
599 | ||
600 | (define_insn "" | |
601 | [(set (reg:SI 29) | |
602 | (plus:SI (reg:SI 29) | |
603 | (match_operand:SI 0 "small_int" "I")))] | |
604 | "TARGET_MIPS16" | |
605 | "addu\\t%$,%$,%0" | |
606 | [(set_attr "type" "arith") | |
607 | (set_attr "mode" "SI") | |
608 | (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_simm8_8" "") | |
0ff83799 MM |
609 | (const_int 4) |
610 | (const_int 8)))]) | |
2bcb2ab3 GK |
611 | |
612 | (define_insn "" | |
613 | [(set (match_operand:SI 0 "register_operand" "=d") | |
614 | (plus:SI (reg:SI 29) | |
615 | (match_operand:SI 1 "small_int" "I")))] | |
616 | "TARGET_MIPS16" | |
617 | "addu\\t%0,%$,%1" | |
618 | [(set_attr "type" "arith") | |
619 | (set_attr "mode" "SI") | |
620 | (set (attr "length") (if_then_else (match_operand:VOID 1 "m16_uimm8_4" "") | |
0ff83799 MM |
621 | (const_int 4) |
622 | (const_int 8)))]) | |
2bcb2ab3 GK |
623 | |
624 | (define_insn "" | |
625 | [(set (match_operand:SI 0 "register_operand" "=d,d,d") | |
626 | (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") | |
627 | (match_operand:SI 2 "arith_operand" "IQ,O,d")))] | |
628 | "TARGET_MIPS16 | |
629 | && (GET_CODE (operands[1]) != REG | |
630 | || REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER | |
631 | || M16_REG_P (REGNO (operands[1])) | |
632 | || REGNO (operands[1]) == ARG_POINTER_REGNUM | |
633 | || REGNO (operands[1]) == FRAME_POINTER_REGNUM | |
634 | || REGNO (operands[1]) == STACK_POINTER_REGNUM) | |
635 | && (GET_CODE (operands[2]) != REG | |
636 | || REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER | |
637 | || M16_REG_P (REGNO (operands[2])) | |
638 | || REGNO (operands[2]) == ARG_POINTER_REGNUM | |
639 | || REGNO (operands[2]) == FRAME_POINTER_REGNUM | |
640 | || REGNO (operands[2]) == STACK_POINTER_REGNUM)" | |
641 | "* | |
642 | { | |
643 | if (REGNO (operands[0]) == REGNO (operands[1])) | |
644 | return \"addu\\t%0,%2\"; | |
645 | return \"addu\\t%0,%1,%2\"; | |
646 | }" | |
647 | [(set_attr "type" "arith") | |
648 | (set_attr "mode" "SI") | |
649 | (set_attr_alternative "length" | |
650 | [(if_then_else (match_operand:VOID 2 "m16_simm8_1" "") | |
0ff83799 MM |
651 | (const_int 4) |
652 | (const_int 8)) | |
2bcb2ab3 | 653 | (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") |
0ff83799 MM |
654 | (const_int 4) |
655 | (const_int 8)) | |
656 | (const_int 4)])]) | |
2bcb2ab3 GK |
657 | |
658 | ||
659 | ;; On the mips16, we can sometimes split an add of a constant which is | |
660 | ;; a 4 byte instruction into two adds which are both 2 byte | |
661 | ;; instructions. There are two cases: one where we are adding a | |
662 | ;; constant plus a register to another register, and one where we are | |
663 | ;; simply adding a constant to a register. | |
664 | ||
665 | (define_split | |
666 | [(set (match_operand:SI 0 "register_operand" "") | |
667 | (plus:SI (match_dup 0) | |
668 | (match_operand:SI 1 "const_int_operand" "")))] | |
669 | "TARGET_MIPS16 && reload_completed | |
670 | && GET_CODE (operands[0]) == REG | |
671 | && M16_REG_P (REGNO (operands[0])) | |
672 | && GET_CODE (operands[1]) == CONST_INT | |
673 | && ((INTVAL (operands[1]) > 0x7f | |
674 | && INTVAL (operands[1]) <= 0x7f + 0x7f) | |
675 | || (INTVAL (operands[1]) < - 0x80 | |
676 | && INTVAL (operands[1]) >= - 0x80 - 0x80))" | |
677 | [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) | |
678 | (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] | |
679 | " | |
680 | { | |
681 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
682 | ||
683 | if (val >= 0) | |
684 | { | |
685 | operands[1] = GEN_INT (0x7f); | |
686 | operands[2] = GEN_INT (val - 0x7f); | |
687 | } | |
688 | else | |
689 | { | |
690 | operands[1] = GEN_INT (- 0x80); | |
691 | operands[2] = GEN_INT (val + 0x80); | |
692 | } | |
693 | }") | |
694 | ||
695 | (define_split | |
696 | [(set (match_operand:SI 0 "register_operand" "") | |
697 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
698 | (match_operand:SI 2 "const_int_operand" "")))] | |
699 | "TARGET_MIPS16 && reload_completed | |
700 | && GET_CODE (operands[0]) == REG | |
701 | && M16_REG_P (REGNO (operands[0])) | |
702 | && GET_CODE (operands[1]) == REG | |
703 | && M16_REG_P (REGNO (operands[1])) | |
704 | && REGNO (operands[0]) != REGNO (operands[1]) | |
705 | && GET_CODE (operands[2]) == CONST_INT | |
706 | && ((INTVAL (operands[2]) > 0x7 | |
707 | && INTVAL (operands[2]) <= 0x7 + 0x7f) | |
708 | || (INTVAL (operands[2]) < - 0x8 | |
709 | && INTVAL (operands[2]) >= - 0x8 - 0x80))" | |
710 | [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) | |
711 | (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] | |
712 | " | |
713 | { | |
714 | HOST_WIDE_INT val = INTVAL (operands[2]); | |
715 | ||
716 | if (val >= 0) | |
717 | { | |
718 | operands[2] = GEN_INT (0x7); | |
719 | operands[3] = GEN_INT (val - 0x7); | |
720 | } | |
721 | else | |
722 | { | |
723 | operands[2] = GEN_INT (- 0x8); | |
724 | operands[3] = GEN_INT (val + 0x8); | |
725 | } | |
726 | }") | |
727 | ||
8ef30996 MM |
728 | (define_expand "adddi3" |
729 | [(parallel [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 ILT |
730 | (plus:DI (match_operand:DI 1 "se_register_operand" "") |
731 | (match_operand:DI 2 "se_arith_operand" ""))) | |
8ef30996 | 732 | (clobber (match_dup 3))])] |
2bcb2ab3 | 733 | "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" |
92b4cee1 MM |
734 | " |
735 | { | |
2bcb2ab3 GK |
736 | /* The mips16 assembler handles -32768 correctly, and so does gas, |
737 | but some other MIPS assemblers think that -32768 needs to be | |
738 | loaded into a register before it can be added in. */ | |
739 | if (! TARGET_MIPS16 | |
740 | && ! TARGET_GAS | |
741 | && GET_CODE (operands[2]) == CONST_INT | |
742 | && INTVAL (operands[2]) == -32768) | |
b0565769 | 743 | operands[2] = force_reg (DImode, operands[2]); |
92b4cee1 | 744 | |
bb621ad7 JW |
745 | if (TARGET_64BIT) |
746 | { | |
747 | emit_insn (gen_adddi3_internal_3 (operands[0], operands[1], | |
748 | operands[2])); | |
749 | DONE; | |
750 | } | |
751 | ||
92b4cee1 MM |
752 | operands[3] = gen_reg_rtx (SImode); |
753 | }") | |
8ef30996 MM |
754 | |
755 | (define_insn "adddi3_internal_1" | |
756 | [(set (match_operand:DI 0 "register_operand" "=d,&d") | |
757 | (plus:DI (match_operand:DI 1 "register_operand" "0,d") | |
758 | (match_operand:DI 2 "register_operand" "d,d"))) | |
759 | (clobber (match_operand:SI 3 "register_operand" "=d,d"))] | |
2bcb2ab3 | 760 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" |
8ef30996 MM |
761 | "* |
762 | { | |
763 | return (REGNO (operands[0]) == REGNO (operands[1]) | |
764 | && REGNO (operands[0]) == REGNO (operands[2])) | |
765 | ? \"srl\\t%3,%L0,31\;sll\\t%M0,%M0,1\;sll\\t%L0,%L1,1\;addu\\t%M0,%M0,%3\" | |
766 | : \"addu\\t%L0,%L1,%L2\;sltu\\t%3,%L0,%L2\;addu\\t%M0,%M1,%M2\;addu\\t%M0,%M0,%3\"; | |
767 | }" | |
92b4cee1 MM |
768 | [(set_attr "type" "darith") |
769 | (set_attr "mode" "DI") | |
0ff83799 | 770 | (set_attr "length" "16")]) |
8ef30996 MM |
771 | |
772 | (define_split | |
773 | [(set (match_operand:DI 0 "register_operand" "") | |
774 | (plus:DI (match_operand:DI 1 "register_operand" "") | |
775 | (match_operand:DI 2 "register_operand" ""))) | |
776 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
777 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
778 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
779 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
780 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
781 | && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2])) | |
782 | && (REGNO (operands[0]) != REGNO (operands[1]) | |
783 | || REGNO (operands[0]) != REGNO (operands[2]))" | |
784 | ||
785 | [(set (subreg:SI (match_dup 0) 0) | |
786 | (plus:SI (subreg:SI (match_dup 1) 0) | |
787 | (subreg:SI (match_dup 2) 0))) | |
788 | ||
789 | (set (match_dup 3) | |
34b650b3 | 790 | (ltu:SI (subreg:SI (match_dup 0) 0) |
8ef30996 MM |
791 | (subreg:SI (match_dup 2) 0))) |
792 | ||
ddef6bc7 JJ |
793 | (set (subreg:SI (match_dup 0) 4) |
794 | (plus:SI (subreg:SI (match_dup 1) 4) | |
795 | (subreg:SI (match_dup 2) 4))) | |
8ef30996 | 796 | |
ddef6bc7 JJ |
797 | (set (subreg:SI (match_dup 0) 4) |
798 | (plus:SI (subreg:SI (match_dup 0) 4) | |
8ef30996 MM |
799 | (match_dup 3)))] |
800 | "") | |
801 | ||
802 | (define_split | |
803 | [(set (match_operand:DI 0 "register_operand" "") | |
804 | (plus:DI (match_operand:DI 1 "register_operand" "") | |
805 | (match_operand:DI 2 "register_operand" ""))) | |
806 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
807 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
808 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
809 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
810 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
811 | && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2])) | |
812 | && (REGNO (operands[0]) != REGNO (operands[1]) | |
813 | || REGNO (operands[0]) != REGNO (operands[2]))" | |
814 | ||
ddef6bc7 JJ |
815 | [(set (subreg:SI (match_dup 0) 4) |
816 | (plus:SI (subreg:SI (match_dup 1) 4) | |
817 | (subreg:SI (match_dup 2) 4))) | |
8ef30996 MM |
818 | |
819 | (set (match_dup 3) | |
ddef6bc7 JJ |
820 | (ltu:SI (subreg:SI (match_dup 0) 4) |
821 | (subreg:SI (match_dup 2) 4))) | |
8ef30996 MM |
822 | |
823 | (set (subreg:SI (match_dup 0) 0) | |
824 | (plus:SI (subreg:SI (match_dup 1) 0) | |
825 | (subreg:SI (match_dup 2) 0))) | |
826 | ||
827 | (set (subreg:SI (match_dup 0) 0) | |
828 | (plus:SI (subreg:SI (match_dup 0) 0) | |
829 | (match_dup 3)))] | |
830 | "") | |
831 | ||
832 | (define_insn "adddi3_internal_2" | |
833 | [(set (match_operand:DI 0 "register_operand" "=d,d,d") | |
834 | (plus:DI (match_operand:DI 1 "register_operand" "%d,%d,%d") | |
835 | (match_operand:DI 2 "small_int" "P,J,N"))) | |
836 | (clobber (match_operand:SI 3 "register_operand" "=d,d,d"))] | |
2bcb2ab3 | 837 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 |
82301b88 JL |
838 | && (TARGET_GAS |
839 | || GET_CODE (operands[2]) != CONST_INT | |
840 | || INTVAL (operands[2]) != -32768)" | |
8ef30996 MM |
841 | "@ |
842 | addu\\t%L0,%L1,%2\;sltu\\t%3,%L0,%2\;addu\\t%M0,%M1,%3 | |
843 | move\\t%L0,%L1\;move\\t%M0,%M1 | |
844 | subu\\t%L0,%L1,%n2\;sltu\\t%3,%L0,%2\;subu\\t%M0,%M1,1\;addu\\t%M0,%M0,%3" | |
92b4cee1 MM |
845 | [(set_attr "type" "darith") |
846 | (set_attr "mode" "DI") | |
0ff83799 | 847 | (set_attr "length" "12,8,16")]) |
8ef30996 MM |
848 | |
849 | (define_split | |
850 | [(set (match_operand:DI 0 "register_operand" "") | |
851 | (plus:DI (match_operand:DI 1 "register_operand" "") | |
852 | (match_operand:DI 2 "small_int" ""))) | |
853 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 GK |
854 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
855 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
856 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
857 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
858 | && INTVAL (operands[2]) > 0" | |
859 | ||
860 | [(set (subreg:SI (match_dup 0) 0) | |
861 | (plus:SI (subreg:SI (match_dup 1) 0) | |
862 | (match_dup 2))) | |
863 | ||
864 | (set (match_dup 3) | |
34b650b3 | 865 | (ltu:SI (subreg:SI (match_dup 0) 0) |
8ef30996 MM |
866 | (match_dup 2))) |
867 | ||
ddef6bc7 JJ |
868 | (set (subreg:SI (match_dup 0) 4) |
869 | (plus:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
870 | (match_dup 3)))] |
871 | "") | |
872 | ||
873 | (define_split | |
874 | [(set (match_operand:DI 0 "register_operand" "") | |
875 | (plus:DI (match_operand:DI 1 "register_operand" "") | |
876 | (match_operand:DI 2 "small_int" ""))) | |
877 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 GK |
878 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
879 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
880 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
881 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
882 | && INTVAL (operands[2]) > 0" | |
883 | ||
ddef6bc7 JJ |
884 | [(set (subreg:SI (match_dup 0) 4) |
885 | (plus:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
886 | (match_dup 2))) |
887 | ||
888 | (set (match_dup 3) | |
ddef6bc7 | 889 | (ltu:SI (subreg:SI (match_dup 0) 4) |
8ef30996 MM |
890 | (match_dup 2))) |
891 | ||
892 | (set (subreg:SI (match_dup 0) 0) | |
893 | (plus:SI (subreg:SI (match_dup 1) 0) | |
894 | (match_dup 3)))] | |
895 | "") | |
bb621ad7 JW |
896 | |
897 | (define_insn "adddi3_internal_3" | |
898 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
899 | (plus:DI (match_operand:DI 1 "se_reg_or_0_operand" "dJ") |
900 | (match_operand:DI 2 "se_arith_operand" "dI")))] | |
2bcb2ab3 GK |
901 | "TARGET_64BIT |
902 | && !TARGET_MIPS16 | |
903 | && (TARGET_GAS | |
904 | || GET_CODE (operands[2]) != CONST_INT | |
905 | || INTVAL (operands[2]) != -32768)" | |
bb621ad7 JW |
906 | "* |
907 | { | |
908 | return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) | |
909 | ? \"dsubu\\t%0,%z1,%n2\" | |
910 | : \"daddu\\t%0,%z1,%2\"; | |
911 | }" | |
912 | [(set_attr "type" "darith") | |
0ff83799 | 913 | (set_attr "mode" "DI")]) |
bb621ad7 | 914 | |
2bcb2ab3 GK |
915 | ;; For the mips16, we need to recognize stack pointer additions |
916 | ;; explicitly, since we don't have a constraint for $sp. These insns | |
917 | ;; will be generated by the save_restore_insns functions. | |
918 | ||
919 | (define_insn "" | |
920 | [(set (reg:DI 29) | |
921 | (plus:DI (reg:DI 29) | |
922 | (match_operand:DI 0 "small_int" "I")))] | |
923 | "TARGET_MIPS16 && TARGET_64BIT" | |
924 | "daddu\\t%$,%$,%0" | |
925 | [(set_attr "type" "arith") | |
926 | (set_attr "mode" "DI") | |
927 | (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_simm8_8" "") | |
0ff83799 MM |
928 | (const_int 4) |
929 | (const_int 8)))]) | |
2bcb2ab3 GK |
930 | |
931 | (define_insn "" | |
932 | [(set (match_operand:DI 0 "register_operand" "=d") | |
933 | (plus:DI (reg:DI 29) | |
934 | (match_operand:DI 1 "small_int" "I")))] | |
935 | "TARGET_MIPS16 && TARGET_64BIT" | |
936 | "daddu\\t%0,%$,%1" | |
937 | [(set_attr "type" "arith") | |
938 | (set_attr "mode" "DI") | |
939 | (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_uimm5_4" "") | |
0ff83799 MM |
940 | (const_int 4) |
941 | (const_int 8)))]) | |
2bcb2ab3 GK |
942 | |
943 | (define_insn "" | |
944 | [(set (match_operand:DI 0 "register_operand" "=d,d,d") | |
945 | (plus:DI (match_operand:DI 1 "register_operand" "0,d,d") | |
946 | (match_operand:DI 2 "arith_operand" "IQ,O,d")))] | |
947 | "TARGET_MIPS16 && TARGET_64BIT | |
948 | && (GET_CODE (operands[1]) != REG | |
949 | || REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER | |
950 | || M16_REG_P (REGNO (operands[1])) | |
951 | || REGNO (operands[1]) == ARG_POINTER_REGNUM | |
952 | || REGNO (operands[1]) == FRAME_POINTER_REGNUM | |
953 | || REGNO (operands[1]) == STACK_POINTER_REGNUM) | |
954 | && (GET_CODE (operands[2]) != REG | |
955 | || REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER | |
956 | || M16_REG_P (REGNO (operands[2])) | |
957 | || REGNO (operands[2]) == ARG_POINTER_REGNUM | |
958 | || REGNO (operands[2]) == FRAME_POINTER_REGNUM | |
959 | || REGNO (operands[2]) == STACK_POINTER_REGNUM)" | |
960 | "* | |
961 | { | |
962 | if (REGNO (operands[0]) == REGNO (operands[1])) | |
963 | return \"daddu\\t%0,%2\"; | |
964 | return \"daddu\\t%0,%1,%2\"; | |
965 | }" | |
966 | [(set_attr "type" "arith") | |
967 | (set_attr "mode" "DI") | |
968 | (set_attr_alternative "length" | |
969 | [(if_then_else (match_operand:VOID 2 "m16_simm5_1" "") | |
0ff83799 MM |
970 | (const_int 4) |
971 | (const_int 8)) | |
2bcb2ab3 | 972 | (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") |
0ff83799 MM |
973 | (const_int 4) |
974 | (const_int 8)) | |
975 | (const_int 4)])]) | |
2bcb2ab3 GK |
976 | |
977 | ||
978 | ;; On the mips16, we can sometimes split an add of a constant which is | |
979 | ;; a 4 byte instruction into two adds which are both 2 byte | |
980 | ;; instructions. There are two cases: one where we are adding a | |
981 | ;; constant plus a register to another register, and one where we are | |
982 | ;; simply adding a constant to a register. | |
983 | ||
984 | (define_split | |
985 | [(set (match_operand:DI 0 "register_operand" "") | |
986 | (plus:DI (match_dup 0) | |
987 | (match_operand:DI 1 "const_int_operand" "")))] | |
988 | "TARGET_MIPS16 && TARGET_64BIT && reload_completed | |
989 | && GET_CODE (operands[0]) == REG | |
990 | && M16_REG_P (REGNO (operands[0])) | |
991 | && GET_CODE (operands[1]) == CONST_INT | |
992 | && ((INTVAL (operands[1]) > 0xf | |
993 | && INTVAL (operands[1]) <= 0xf + 0xf) | |
994 | || (INTVAL (operands[1]) < - 0x10 | |
995 | && INTVAL (operands[1]) >= - 0x10 - 0x10))" | |
996 | [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) | |
997 | (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))] | |
998 | " | |
999 | { | |
1000 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
1001 | ||
1002 | if (val >= 0) | |
1003 | { | |
1004 | operands[1] = GEN_INT (0xf); | |
1005 | operands[2] = GEN_INT (val - 0xf); | |
1006 | } | |
1007 | else | |
1008 | { | |
1009 | operands[1] = GEN_INT (- 0x10); | |
1010 | operands[2] = GEN_INT (val + 0x10); | |
1011 | } | |
1012 | }") | |
1013 | ||
1014 | (define_split | |
1015 | [(set (match_operand:DI 0 "register_operand" "") | |
1016 | (plus:DI (match_operand:DI 1 "register_operand" "") | |
1017 | (match_operand:DI 2 "const_int_operand" "")))] | |
1018 | "TARGET_MIPS16 && TARGET_64BIT && reload_completed | |
1019 | && GET_CODE (operands[0]) == REG | |
1020 | && M16_REG_P (REGNO (operands[0])) | |
1021 | && GET_CODE (operands[1]) == REG | |
1022 | && M16_REG_P (REGNO (operands[1])) | |
1023 | && REGNO (operands[0]) != REGNO (operands[1]) | |
1024 | && GET_CODE (operands[2]) == CONST_INT | |
1025 | && ((INTVAL (operands[2]) > 0x7 | |
1026 | && INTVAL (operands[2]) <= 0x7 + 0xf) | |
1027 | || (INTVAL (operands[2]) < - 0x8 | |
1028 | && INTVAL (operands[2]) >= - 0x8 - 0x10))" | |
1029 | [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) | |
1030 | (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] | |
1031 | " | |
1032 | { | |
1033 | HOST_WIDE_INT val = INTVAL (operands[2]); | |
1034 | ||
1035 | if (val >= 0) | |
1036 | { | |
1037 | operands[2] = GEN_INT (0x7); | |
1038 | operands[3] = GEN_INT (val - 0x7); | |
1039 | } | |
1040 | else | |
1041 | { | |
1042 | operands[2] = GEN_INT (- 0x8); | |
1043 | operands[3] = GEN_INT (val + 0x8); | |
1044 | } | |
1045 | }") | |
bb621ad7 JW |
1046 | |
1047 | (define_insn "addsi3_internal_2" | |
1048 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1049 | (sign_extend:DI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") | |
1050 | (match_operand:SI 2 "arith_operand" "dI"))))] | |
2bcb2ab3 GK |
1051 | "TARGET_64BIT |
1052 | && !TARGET_MIPS16 | |
1053 | && (TARGET_GAS | |
1054 | || GET_CODE (operands[2]) != CONST_INT | |
1055 | || INTVAL (operands[2]) != -32768)" | |
bb621ad7 JW |
1056 | "* |
1057 | { | |
1058 | return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) | |
1059 | ? \"subu\\t%0,%z1,%n2\" | |
1060 | : \"addu\\t%0,%z1,%2\"; | |
1061 | }" | |
1062 | [(set_attr "type" "arith") | |
0ff83799 | 1063 | (set_attr "mode" "SI")]) |
bb621ad7 | 1064 | |
2bcb2ab3 GK |
1065 | (define_insn "" |
1066 | [(set (match_operand:DI 0 "register_operand" "=d,d,d") | |
1067 | (sign_extend:DI (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") | |
1068 | (match_operand:SI 2 "arith_operand" "I,O,d"))))] | |
1069 | "TARGET_MIPS16 && TARGET_64BIT" | |
1070 | "* | |
1071 | { | |
1072 | if (REGNO (operands[0]) == REGNO (operands[1])) | |
1073 | return \"addu\\t%0,%2\"; | |
1074 | return \"addu\\t%0,%1,%2\"; | |
1075 | }" | |
1076 | [(set_attr "type" "arith") | |
1077 | (set_attr "mode" "SI") | |
1078 | (set_attr_alternative "length" | |
1079 | [(if_then_else (match_operand:VOID 2 "m16_simm8_1" "") | |
0ff83799 MM |
1080 | (const_int 4) |
1081 | (const_int 8)) | |
2bcb2ab3 | 1082 | (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") |
0ff83799 MM |
1083 | (const_int 4) |
1084 | (const_int 8)) | |
1085 | (const_int 4)])]) | |
2bcb2ab3 | 1086 | |
8ef30996 MM |
1087 | \f |
1088 | ;; | |
1089 | ;; .................... | |
1090 | ;; | |
1091 | ;; SUBTRACTION | |
1092 | ;; | |
1093 | ;; .................... | |
1094 | ;; | |
1095 | ||
1096 | (define_insn "subdf3" | |
1097 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1098 | (minus:DF (match_operand:DF 1 "register_operand" "f") | |
1099 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 1100 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
1101 | "sub.d\\t%0,%1,%2" |
1102 | [(set_attr "type" "fadd") | |
0ff83799 | 1103 | (set_attr "mode" "DF")]) |
8ef30996 MM |
1104 | |
1105 | (define_insn "subsf3" | |
1106 | [(set (match_operand:SF 0 "register_operand" "=f") | |
1107 | (minus:SF (match_operand:SF 1 "register_operand" "f") | |
1108 | (match_operand:SF 2 "register_operand" "f")))] | |
1109 | "TARGET_HARD_FLOAT" | |
1110 | "sub.s\\t%0,%1,%2" | |
1111 | [(set_attr "type" "fadd") | |
0ff83799 | 1112 | (set_attr "mode" "SF")]) |
8ef30996 | 1113 | |
71cd5224 | 1114 | (define_expand "subsi3" |
8ef30996 MM |
1115 | [(set (match_operand:SI 0 "register_operand" "=d") |
1116 | (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") | |
1117 | (match_operand:SI 2 "arith_operand" "dI")))] | |
1118 | "" | |
71cd5224 RS |
1119 | " |
1120 | { | |
2bcb2ab3 GK |
1121 | if (GET_CODE (operands[2]) == CONST_INT |
1122 | && (INTVAL (operands[2]) == -32768 | |
1123 | || (TARGET_MIPS16 | |
1124 | && INTVAL (operands[2]) == -0x4000))) | |
71cd5224 RS |
1125 | operands[2] = force_reg (SImode, operands[2]); |
1126 | }") | |
1127 | ||
1128 | (define_insn "subsi3_internal" | |
1129 | [(set (match_operand:SI 0 "register_operand" "=d") | |
1130 | (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") | |
1131 | (match_operand:SI 2 "arith_operand" "dI")))] | |
2bcb2ab3 GK |
1132 | "!TARGET_MIPS16 |
1133 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" | |
9b190d1c | 1134 | "subu\\t%0,%z1,%2" |
8ef30996 | 1135 | [(set_attr "type" "arith") |
0ff83799 | 1136 | (set_attr "mode" "SI")]) |
8ef30996 | 1137 | |
2bcb2ab3 GK |
1138 | ;; For the mips16, we need to recognize stack pointer subtractions |
1139 | ;; explicitly, since we don't have a constraint for $sp. These insns | |
1140 | ;; will be generated by the save_restore_insns functions. | |
1141 | ||
1142 | (define_insn "" | |
1143 | [(set (reg:SI 29) | |
1144 | (minus:SI (reg:SI 29) | |
1145 | (match_operand:SI 0 "small_int" "I")))] | |
1146 | "TARGET_MIPS16 | |
1147 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" | |
1148 | "addu\\t%$,%$,%n0" | |
1149 | [(set_attr "type" "arith") | |
1150 | (set_attr "mode" "SI") | |
1151 | (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_nsimm8_8" "") | |
0ff83799 MM |
1152 | (const_int 4) |
1153 | (const_int 8)))]) | |
2bcb2ab3 GK |
1154 | |
1155 | (define_insn "" | |
1156 | [(set (match_operand:SI 0 "register_operand" "=d") | |
1157 | (minus:SI (reg:SI 29) | |
1158 | (match_operand:SI 1 "small_int" "I")))] | |
1159 | "TARGET_MIPS16 | |
1160 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" | |
1161 | "addu\\t%0,%$,%n1" | |
1162 | [(set_attr "type" "arith") | |
1163 | (set_attr "mode" "SI") | |
1164 | (set (attr "length") (if_then_else (match_operand:VOID 1 "m16_nuimm8_4" "") | |
0ff83799 MM |
1165 | (const_int 4) |
1166 | (const_int 8)))]) | |
2bcb2ab3 GK |
1167 | |
1168 | ||
1169 | (define_insn "" | |
1170 | [(set (match_operand:SI 0 "register_operand" "=d,d,d") | |
1171 | (minus:SI (match_operand:SI 1 "register_operand" "0,d,d") | |
1172 | (match_operand:SI 2 "arith_operand" "I,O,d")))] | |
1173 | "TARGET_MIPS16 | |
1174 | && (GET_CODE (operands[2]) != CONST_INT | |
1175 | || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))" | |
1176 | "* | |
1177 | { | |
1178 | if (REGNO (operands[0]) == REGNO (operands[1])) | |
1179 | return \"subu\\t%0,%2\"; | |
1180 | return \"subu\\t%0,%1,%2\"; | |
1181 | }" | |
1182 | [(set_attr "type" "arith") | |
1183 | (set_attr "mode" "SI") | |
1184 | (set_attr_alternative "length" | |
1185 | [(if_then_else (match_operand:VOID 2 "m16_nsimm8_1" "") | |
0ff83799 MM |
1186 | (const_int 4) |
1187 | (const_int 8)) | |
2bcb2ab3 | 1188 | (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "") |
0ff83799 MM |
1189 | (const_int 4) |
1190 | (const_int 8)) | |
1191 | (const_int 4)])]) | |
2bcb2ab3 GK |
1192 | |
1193 | ;; On the mips16, we can sometimes split an subtract of a constant | |
1194 | ;; which is a 4 byte instruction into two adds which are both 2 byte | |
1195 | ;; instructions. There are two cases: one where we are setting a | |
1196 | ;; register to a register minus a constant, and one where we are | |
1197 | ;; simply subtracting a constant from a register. | |
1198 | ||
1199 | (define_split | |
1200 | [(set (match_operand:SI 0 "register_operand" "") | |
1201 | (minus:SI (match_dup 0) | |
1202 | (match_operand:SI 1 "const_int_operand" "")))] | |
1203 | "TARGET_MIPS16 && reload_completed | |
1204 | && GET_CODE (operands[0]) == REG | |
1205 | && M16_REG_P (REGNO (operands[0])) | |
1206 | && GET_CODE (operands[1]) == CONST_INT | |
1207 | && ((INTVAL (operands[1]) > 0x80 | |
1208 | && INTVAL (operands[1]) <= 0x80 + 0x80) | |
1209 | || (INTVAL (operands[1]) < - 0x7f | |
1210 | && INTVAL (operands[1]) >= - 0x7f - 0x7f))" | |
1211 | [(set (match_dup 0) (minus:SI (match_dup 0) (match_dup 1))) | |
1212 | (set (match_dup 0) (minus:SI (match_dup 0) (match_dup 2)))] | |
1213 | " | |
1214 | { | |
1215 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
1216 | ||
1217 | if (val >= 0) | |
1218 | { | |
1219 | operands[1] = GEN_INT (0x80); | |
1220 | operands[2] = GEN_INT (val - 0x80); | |
1221 | } | |
1222 | else | |
1223 | { | |
1224 | operands[1] = GEN_INT (- 0x7f); | |
1225 | operands[2] = GEN_INT (val + 0x7f); | |
1226 | } | |
1227 | }") | |
1228 | ||
1229 | (define_split | |
1230 | [(set (match_operand:SI 0 "register_operand" "") | |
1231 | (minus:SI (match_operand:SI 1 "register_operand" "") | |
1232 | (match_operand:SI 2 "const_int_operand" "")))] | |
1233 | "TARGET_MIPS16 && reload_completed | |
1234 | && GET_CODE (operands[0]) == REG | |
1235 | && M16_REG_P (REGNO (operands[0])) | |
1236 | && GET_CODE (operands[1]) == REG | |
1237 | && M16_REG_P (REGNO (operands[1])) | |
1238 | && REGNO (operands[0]) != REGNO (operands[1]) | |
1239 | && GET_CODE (operands[2]) == CONST_INT | |
1240 | && ((INTVAL (operands[2]) > 0x8 | |
1241 | && INTVAL (operands[2]) <= 0x8 + 0x80) | |
1242 | || (INTVAL (operands[2]) < - 0x7 | |
1243 | && INTVAL (operands[2]) >= - 0x7 - 0x7f))" | |
1244 | [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) | |
1245 | (set (match_dup 0) (minus:SI (match_dup 0) (match_dup 3)))] | |
1246 | " | |
1247 | { | |
1248 | HOST_WIDE_INT val = INTVAL (operands[2]); | |
1249 | ||
1250 | if (val >= 0) | |
1251 | { | |
1252 | operands[2] = GEN_INT (0x8); | |
1253 | operands[3] = GEN_INT (val - 0x8); | |
1254 | } | |
1255 | else | |
1256 | { | |
1257 | operands[2] = GEN_INT (- 0x7); | |
1258 | operands[3] = GEN_INT (val + 0x7); | |
1259 | } | |
1260 | }") | |
1261 | ||
8ef30996 MM |
1262 | (define_expand "subdi3" |
1263 | [(parallel [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
1264 | (minus:DI (match_operand:DI 1 "se_register_operand" "d") |
1265 | (match_operand:DI 2 "se_register_operand" "d"))) | |
8ef30996 | 1266 | (clobber (match_dup 3))])] |
2bcb2ab3 | 1267 | "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" |
bb621ad7 JW |
1268 | " |
1269 | { | |
1270 | if (TARGET_64BIT) | |
1271 | { | |
1272 | emit_insn (gen_subdi3_internal_3 (operands[0], operands[1], | |
1273 | operands[2])); | |
1274 | DONE; | |
1275 | } | |
1276 | ||
1277 | operands[3] = gen_reg_rtx (SImode); | |
1278 | }") | |
8ef30996 MM |
1279 | |
1280 | (define_insn "subdi3_internal" | |
1281 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1282 | (minus:DI (match_operand:DI 1 "register_operand" "d") | |
1283 | (match_operand:DI 2 "register_operand" "d"))) | |
1284 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 | 1285 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" |
8ef30996 MM |
1286 | "sltu\\t%3,%L1,%L2\;subu\\t%L0,%L1,%L2\;subu\\t%M0,%M1,%M2\;subu\\t%M0,%M0,%3" |
1287 | [(set_attr "type" "darith") | |
1288 | (set_attr "mode" "DI") | |
0ff83799 | 1289 | (set_attr "length" "16")]) |
8ef30996 MM |
1290 | |
1291 | (define_split | |
1292 | [(set (match_operand:DI 0 "register_operand" "") | |
1293 | (minus:DI (match_operand:DI 1 "register_operand" "") | |
1294 | (match_operand:DI 2 "register_operand" ""))) | |
1295 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
1296 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
1297 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
1298 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
1299 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
1300 | && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" | |
1301 | ||
1302 | [(set (match_dup 3) | |
34b650b3 | 1303 | (ltu:SI (subreg:SI (match_dup 1) 0) |
6d518002 | 1304 | (subreg:SI (match_dup 2) 0))) |
8ef30996 MM |
1305 | |
1306 | (set (subreg:SI (match_dup 0) 0) | |
1307 | (minus:SI (subreg:SI (match_dup 1) 0) | |
1308 | (subreg:SI (match_dup 2) 0))) | |
1309 | ||
ddef6bc7 JJ |
1310 | (set (subreg:SI (match_dup 0) 4) |
1311 | (minus:SI (subreg:SI (match_dup 1) 4) | |
1312 | (subreg:SI (match_dup 2) 4))) | |
8ef30996 | 1313 | |
ddef6bc7 JJ |
1314 | (set (subreg:SI (match_dup 0) 4) |
1315 | (minus:SI (subreg:SI (match_dup 0) 4) | |
8ef30996 MM |
1316 | (match_dup 3)))] |
1317 | "") | |
1318 | ||
1319 | (define_split | |
1320 | [(set (match_operand:DI 0 "register_operand" "") | |
1321 | (minus:DI (match_operand:DI 1 "register_operand" "") | |
1322 | (match_operand:DI 2 "register_operand" ""))) | |
1323 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
1324 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
1325 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
1326 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
1327 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
1328 | && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" | |
1329 | ||
1330 | [(set (match_dup 3) | |
ddef6bc7 JJ |
1331 | (ltu:SI (subreg:SI (match_dup 1) 4) |
1332 | (subreg:SI (match_dup 2) 4))) | |
8ef30996 | 1333 | |
ddef6bc7 JJ |
1334 | (set (subreg:SI (match_dup 0) 4) |
1335 | (minus:SI (subreg:SI (match_dup 1) 4) | |
1336 | (subreg:SI (match_dup 2) 4))) | |
8ef30996 MM |
1337 | |
1338 | (set (subreg:SI (match_dup 0) 0) | |
1339 | (minus:SI (subreg:SI (match_dup 1) 0) | |
1340 | (subreg:SI (match_dup 2) 0))) | |
1341 | ||
1342 | (set (subreg:SI (match_dup 0) 0) | |
1343 | (minus:SI (subreg:SI (match_dup 0) 0) | |
1344 | (match_dup 3)))] | |
1345 | "") | |
1346 | ||
1347 | (define_insn "subdi3_internal_2" | |
1348 | [(set (match_operand:DI 0 "register_operand" "=d,d,d") | |
1349 | (minus:DI (match_operand:DI 1 "register_operand" "d,d,d") | |
1350 | (match_operand:DI 2 "small_int" "P,J,N"))) | |
1351 | (clobber (match_operand:SI 3 "register_operand" "=d,d,d"))] | |
2bcb2ab3 GK |
1352 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 |
1353 | && INTVAL (operands[2]) != -32768" | |
8ef30996 MM |
1354 | "@ |
1355 | sltu\\t%3,%L1,%2\;subu\\t%L0,%L1,%2\;subu\\t%M0,%M1,%3 | |
1356 | move\\t%L0,%L1\;move\\t%M0,%M1 | |
1357 | sltu\\t%3,%L1,%2\;subu\\t%L0,%L1,%2\;subu\\t%M0,%M1,1\;subu\\t%M0,%M0,%3" | |
92b4cee1 MM |
1358 | [(set_attr "type" "darith") |
1359 | (set_attr "mode" "DI") | |
0ff83799 | 1360 | (set_attr "length" "12,8,16")]) |
8ef30996 MM |
1361 | |
1362 | (define_split | |
1363 | [(set (match_operand:DI 0 "register_operand" "") | |
1364 | (minus:DI (match_operand:DI 1 "register_operand" "") | |
1365 | (match_operand:DI 2 "small_int" ""))) | |
1366 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
1367 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
1368 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
1369 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
1370 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
1371 | && INTVAL (operands[2]) > 0" | |
1372 | ||
1373 | [(set (match_dup 3) | |
34b650b3 | 1374 | (ltu:SI (subreg:SI (match_dup 1) 0) |
8ef30996 MM |
1375 | (match_dup 2))) |
1376 | ||
1377 | (set (subreg:SI (match_dup 0) 0) | |
1378 | (minus:SI (subreg:SI (match_dup 1) 0) | |
1379 | (match_dup 2))) | |
1380 | ||
ddef6bc7 JJ |
1381 | (set (subreg:SI (match_dup 0) 4) |
1382 | (minus:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
1383 | (match_dup 3)))] |
1384 | "") | |
1385 | ||
1386 | (define_split | |
1387 | [(set (match_operand:DI 0 "register_operand" "") | |
1388 | (minus:DI (match_operand:DI 1 "register_operand" "") | |
1389 | (match_operand:DI 2 "small_int" ""))) | |
1390 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
1391 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
1392 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
1393 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
1394 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
1395 | && INTVAL (operands[2]) > 0" | |
1396 | ||
1397 | [(set (match_dup 3) | |
ddef6bc7 | 1398 | (ltu:SI (subreg:SI (match_dup 1) 4) |
8ef30996 MM |
1399 | (match_dup 2))) |
1400 | ||
ddef6bc7 JJ |
1401 | (set (subreg:SI (match_dup 0) 4) |
1402 | (minus:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
1403 | (match_dup 2))) |
1404 | ||
1405 | (set (subreg:SI (match_dup 0) 0) | |
1406 | (minus:SI (subreg:SI (match_dup 1) 0) | |
1407 | (match_dup 3)))] | |
1408 | "") | |
1409 | ||
bb621ad7 JW |
1410 | (define_insn "subdi3_internal_3" |
1411 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
1412 | (minus:DI (match_operand:DI 1 "se_reg_or_0_operand" "dJ") |
1413 | (match_operand:DI 2 "se_arith_operand" "dI")))] | |
2bcb2ab3 GK |
1414 | "TARGET_64BIT && !TARGET_MIPS16 |
1415 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" | |
bb621ad7 JW |
1416 | "* |
1417 | { | |
1418 | return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) | |
1419 | ? \"daddu\\t%0,%z1,%n2\" | |
1420 | : \"dsubu\\t%0,%z1,%2\"; | |
1421 | }" | |
1422 | [(set_attr "type" "darith") | |
0ff83799 | 1423 | (set_attr "mode" "DI")]) |
bb621ad7 | 1424 | |
2bcb2ab3 GK |
1425 | ;; For the mips16, we need to recognize stack pointer subtractions |
1426 | ;; explicitly, since we don't have a constraint for $sp. These insns | |
1427 | ;; will be generated by the save_restore_insns functions. | |
1428 | ||
1429 | (define_insn "" | |
1430 | [(set (reg:DI 29) | |
1431 | (minus:DI (reg:DI 29) | |
1432 | (match_operand:DI 0 "small_int" "I")))] | |
1433 | "TARGET_MIPS16 | |
1434 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" | |
1435 | "daddu\\t%$,%$,%n0" | |
1436 | [(set_attr "type" "arith") | |
1437 | (set_attr "mode" "DI") | |
1438 | (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_nsimm8_8" "") | |
0ff83799 MM |
1439 | (const_int 4) |
1440 | (const_int 8)))]) | |
2bcb2ab3 GK |
1441 | |
1442 | (define_insn "" | |
1443 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1444 | (minus:DI (reg:DI 29) | |
1445 | (match_operand:DI 1 "small_int" "I")))] | |
1446 | "TARGET_MIPS16 | |
1447 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" | |
1448 | "daddu\\t%0,%$,%n1" | |
1449 | [(set_attr "type" "arith") | |
1450 | (set_attr "mode" "DI") | |
1451 | (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_nuimm5_4" "") | |
0ff83799 MM |
1452 | (const_int 4) |
1453 | (const_int 8)))]) | |
2bcb2ab3 GK |
1454 | |
1455 | (define_insn "" | |
1456 | [(set (match_operand:DI 0 "register_operand" "=d,d,d") | |
1457 | (minus:DI (match_operand:DI 1 "register_operand" "0,d,d") | |
1458 | (match_operand:DI 2 "arith_operand" "I,O,d")))] | |
1459 | "TARGET_MIPS16 | |
1460 | && (GET_CODE (operands[2]) != CONST_INT | |
1461 | || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))" | |
1462 | "* | |
1463 | { | |
1464 | if (REGNO (operands[0]) == REGNO (operands[1])) | |
1465 | return \"dsubu\\t%0,%2\"; | |
1466 | return \"dsubu\\t%0,%1,%2\"; | |
1467 | }" | |
1468 | [(set_attr "type" "arith") | |
1469 | (set_attr "mode" "DI") | |
1470 | (set_attr_alternative "length" | |
1471 | [(if_then_else (match_operand:VOID 2 "m16_nsimm5_1" "") | |
0ff83799 MM |
1472 | (const_int 4) |
1473 | (const_int 8)) | |
2bcb2ab3 | 1474 | (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "") |
0ff83799 MM |
1475 | (const_int 4) |
1476 | (const_int 8)) | |
1477 | (const_int 4)])]) | |
2bcb2ab3 GK |
1478 | |
1479 | ;; On the mips16, we can sometimes split an add of a constant which is | |
1480 | ;; a 4 byte instruction into two adds which are both 2 byte | |
1481 | ;; instructions. There are two cases: one where we are adding a | |
1482 | ;; constant plus a register to another register, and one where we are | |
1483 | ;; simply adding a constant to a register. | |
1484 | ||
1485 | (define_split | |
1486 | [(set (match_operand:DI 0 "register_operand" "") | |
1487 | (minus:DI (match_dup 0) | |
1488 | (match_operand:DI 1 "const_int_operand" "")))] | |
1489 | "TARGET_MIPS16 && TARGET_64BIT && reload_completed | |
1490 | && GET_CODE (operands[0]) == REG | |
1491 | && M16_REG_P (REGNO (operands[0])) | |
1492 | && GET_CODE (operands[1]) == CONST_INT | |
1493 | && ((INTVAL (operands[1]) > 0x10 | |
1494 | && INTVAL (operands[1]) <= 0x10 + 0x10) | |
1495 | || (INTVAL (operands[1]) < - 0xf | |
1496 | && INTVAL (operands[1]) >= - 0xf - 0xf))" | |
1497 | [(set (match_dup 0) (minus:DI (match_dup 0) (match_dup 1))) | |
1498 | (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 2)))] | |
1499 | " | |
1500 | { | |
1501 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
1502 | ||
1503 | if (val >= 0) | |
1504 | { | |
1505 | operands[1] = GEN_INT (0xf); | |
1506 | operands[2] = GEN_INT (val - 0xf); | |
1507 | } | |
1508 | else | |
1509 | { | |
1510 | operands[1] = GEN_INT (- 0x10); | |
1511 | operands[2] = GEN_INT (val + 0x10); | |
1512 | } | |
1513 | }") | |
1514 | ||
1515 | (define_split | |
1516 | [(set (match_operand:DI 0 "register_operand" "") | |
1517 | (minus:DI (match_operand:DI 1 "register_operand" "") | |
1518 | (match_operand:DI 2 "const_int_operand" "")))] | |
1519 | "TARGET_MIPS16 && TARGET_64BIT && reload_completed | |
1520 | && GET_CODE (operands[0]) == REG | |
1521 | && M16_REG_P (REGNO (operands[0])) | |
1522 | && GET_CODE (operands[1]) == REG | |
1523 | && M16_REG_P (REGNO (operands[1])) | |
1524 | && REGNO (operands[0]) != REGNO (operands[1]) | |
1525 | && GET_CODE (operands[2]) == CONST_INT | |
1526 | && ((INTVAL (operands[2]) > 0x8 | |
1527 | && INTVAL (operands[2]) <= 0x8 + 0x10) | |
1528 | || (INTVAL (operands[2]) < - 0x7 | |
1529 | && INTVAL (operands[2]) >= - 0x7 - 0xf))" | |
1530 | [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2))) | |
1531 | (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 3)))] | |
1532 | " | |
1533 | { | |
1534 | HOST_WIDE_INT val = INTVAL (operands[2]); | |
1535 | ||
1536 | if (val >= 0) | |
1537 | { | |
1538 | operands[2] = GEN_INT (0x8); | |
1539 | operands[3] = GEN_INT (val - 0x8); | |
1540 | } | |
1541 | else | |
1542 | { | |
1543 | operands[2] = GEN_INT (- 0x7); | |
1544 | operands[3] = GEN_INT (val + 0x7); | |
1545 | } | |
1546 | }") | |
bb621ad7 JW |
1547 | |
1548 | (define_insn "subsi3_internal_2" | |
1549 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1550 | (sign_extend:DI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") | |
1551 | (match_operand:SI 2 "arith_operand" "dI"))))] | |
2bcb2ab3 GK |
1552 | "TARGET_64BIT && !TARGET_MIPS16 |
1553 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" | |
bb621ad7 JW |
1554 | "* |
1555 | { | |
1556 | return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) | |
1557 | ? \"addu\\t%0,%z1,%n2\" | |
1558 | : \"subu\\t%0,%z1,%2\"; | |
1559 | }" | |
1560 | [(set_attr "type" "arith") | |
0ff83799 | 1561 | (set_attr "mode" "DI")]) |
bb621ad7 | 1562 | |
2bcb2ab3 GK |
1563 | (define_insn "" |
1564 | [(set (match_operand:DI 0 "register_operand" "=d,d,d") | |
1565 | (sign_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "0,d,d") | |
1566 | (match_operand:SI 2 "arith_operand" "I,O,d"))))] | |
1567 | "TARGET_64BIT && TARGET_MIPS16 | |
1568 | && (GET_CODE (operands[2]) != CONST_INT | |
1569 | || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))" | |
1570 | "* | |
1571 | { | |
1572 | if (REGNO (operands[0]) == REGNO (operands[1])) | |
1573 | return \"subu\\t%0,%2\"; | |
1574 | return \"subu\\t%0,%1,%2\"; | |
1575 | }" | |
1576 | [(set_attr "type" "arith") | |
1577 | (set_attr "mode" "SI") | |
1578 | (set_attr_alternative "length" | |
1579 | [(if_then_else (match_operand:VOID 2 "m16_nsimm8_1" "") | |
0ff83799 MM |
1580 | (const_int 4) |
1581 | (const_int 8)) | |
2bcb2ab3 | 1582 | (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "") |
0ff83799 MM |
1583 | (const_int 4) |
1584 | (const_int 8)) | |
1585 | (const_int 4)])]) | |
2bcb2ab3 GK |
1586 | |
1587 | ||
8ef30996 MM |
1588 | \f |
1589 | ;; | |
1590 | ;; .................... | |
1591 | ;; | |
1592 | ;; MULTIPLICATION | |
1593 | ;; | |
1594 | ;; .................... | |
1595 | ;; | |
1596 | ||
aa4e54c4 JW |
1597 | ;; Early Vr4300 silicon has a CPU bug where multiplies with certain |
1598 | ;; operands may corrupt immediately following multiplies. This is a | |
1599 | ;; simple fix to insert NOPs. | |
8fbaea49 JW |
1600 | |
1601 | (define_expand "muldf3" | |
8ef30996 MM |
1602 | [(set (match_operand:DF 0 "register_operand" "=f") |
1603 | (mult:DF (match_operand:DF 1 "register_operand" "f") | |
1604 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 1605 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8fbaea49 JW |
1606 | " |
1607 | { | |
1608 | if (mips_cpu != PROCESSOR_R4300) | |
1609 | emit_insn (gen_muldf3_internal (operands[0], operands[1], operands[2])); | |
1610 | else | |
1611 | emit_insn (gen_muldf3_r4300 (operands[0], operands[1], operands[2])); | |
1612 | DONE; | |
1613 | }") | |
1614 | ||
1615 | (define_insn "muldf3_internal" | |
1616 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1617 | (mult:DF (match_operand:DF 1 "register_operand" "f") | |
1618 | (match_operand:DF 2 "register_operand" "f")))] | |
1619 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && mips_cpu != PROCESSOR_R4300" | |
8ef30996 MM |
1620 | "mul.d\\t%0,%1,%2" |
1621 | [(set_attr "type" "fmul") | |
0ff83799 | 1622 | (set_attr "mode" "DF")]) |
8ef30996 | 1623 | |
8fbaea49 JW |
1624 | (define_insn "muldf3_r4300" |
1625 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1626 | (mult:DF (match_operand:DF 1 "register_operand" "f") | |
1627 | (match_operand:DF 2 "register_operand" "f")))] | |
1628 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && mips_cpu == PROCESSOR_R4300" | |
1629 | "* | |
1630 | { | |
1631 | output_asm_insn (\"mul.d\\t%0,%1,%2\", operands); | |
1632 | if (TARGET_4300_MUL_FIX) | |
1633 | output_asm_insn (\"nop\", operands); | |
1634 | return \"\"; | |
1635 | }" | |
1636 | [(set_attr "type" "fmul") | |
1637 | (set_attr "mode" "DF") | |
0ff83799 | 1638 | (set_attr "length" "8")]) ;; mul.d + nop |
8fbaea49 JW |
1639 | |
1640 | (define_expand "mulsf3" | |
8ef30996 MM |
1641 | [(set (match_operand:SF 0 "register_operand" "=f") |
1642 | (mult:SF (match_operand:SF 1 "register_operand" "f") | |
1643 | (match_operand:SF 2 "register_operand" "f")))] | |
1644 | "TARGET_HARD_FLOAT" | |
8fbaea49 JW |
1645 | " |
1646 | { | |
1647 | if (mips_cpu != PROCESSOR_R4300) | |
1648 | emit_insn( gen_mulsf3_internal (operands[0], operands[1], operands[2])); | |
1649 | else | |
1650 | emit_insn( gen_mulsf3_r4300 (operands[0], operands[1], operands[2])); | |
1651 | DONE; | |
1652 | }") | |
1653 | ||
1654 | (define_insn "mulsf3_internal" | |
1655 | [(set (match_operand:SF 0 "register_operand" "=f") | |
1656 | (mult:SF (match_operand:SF 1 "register_operand" "f") | |
1657 | (match_operand:SF 2 "register_operand" "f")))] | |
1658 | "TARGET_HARD_FLOAT && mips_cpu != PROCESSOR_R4300" | |
8ef30996 MM |
1659 | "mul.s\\t%0,%1,%2" |
1660 | [(set_attr "type" "fmul") | |
0ff83799 | 1661 | (set_attr "mode" "SF")]) |
8ef30996 | 1662 | |
8fbaea49 JW |
1663 | (define_insn "mulsf3_r4300" |
1664 | [(set (match_operand:SF 0 "register_operand" "=f") | |
1665 | (mult:SF (match_operand:SF 1 "register_operand" "f") | |
1666 | (match_operand:SF 2 "register_operand" "f")))] | |
1667 | "TARGET_HARD_FLOAT && mips_cpu == PROCESSOR_R4300" | |
1668 | "* | |
1669 | { | |
1670 | output_asm_insn (\"mul.s\\t%0,%1,%2\", operands); | |
1671 | if (TARGET_4300_MUL_FIX) | |
1672 | output_asm_insn (\"nop\", operands); | |
1673 | return \"\"; | |
1674 | }" | |
1675 | [(set_attr "type" "fmul") | |
1676 | (set_attr "mode" "SF") | |
0ff83799 | 1677 | (set_attr "length" "8")]) ;; mul.s + nop |
8fbaea49 | 1678 | |
cb923660 | 1679 | |
46299de9 ILT |
1680 | ;; ??? The R4000 (only) has a cpu bug. If a double-word shift executes while |
1681 | ;; a multiply is in progress, it may give an incorrect result. Avoid | |
1682 | ;; this by keeping the mflo with the mult on the R4000. | |
1683 | ||
1684 | (define_expand "mulsi3" | |
1685 | [(set (match_operand:SI 0 "register_operand" "=l") | |
8ef30996 MM |
1686 | (mult:SI (match_operand:SI 1 "register_operand" "d") |
1687 | (match_operand:SI 2 "register_operand" "d"))) | |
225b8835 ILT |
1688 | (clobber (match_scratch:SI 3 "=h")) |
1689 | (clobber (match_scratch:SI 4 "=a"))] | |
8ef30996 | 1690 | "" |
46299de9 ILT |
1691 | " |
1692 | { | |
e4f5c5d6 | 1693 | if (HAVE_mulsi3_mult3) |
e9a25f70 | 1694 | emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2])); |
2bcb2ab3 | 1695 | else if (mips_cpu != PROCESSOR_R4000 || TARGET_MIPS16) |
46299de9 ILT |
1696 | emit_insn (gen_mulsi3_internal (operands[0], operands[1], operands[2])); |
1697 | else | |
1698 | emit_insn (gen_mulsi3_r4000 (operands[0], operands[1], operands[2])); | |
1699 | DONE; | |
1700 | }") | |
1701 | ||
e9a25f70 | 1702 | (define_insn "mulsi3_mult3" |
e4f5c5d6 | 1703 | [(set (match_operand:SI 0 "register_operand" "=d,l") |
cb923660 KR |
1704 | (mult:SI (match_operand:SI 1 "register_operand" "d,d") |
1705 | (match_operand:SI 2 "register_operand" "d,d"))) | |
1706 | (clobber (match_scratch:SI 3 "=h,h")) | |
1707 | (clobber (match_scratch:SI 4 "=l,X")) | |
1708 | (clobber (match_scratch:SI 5 "=a,a"))] | |
e4f5c5d6 KR |
1709 | "GENERATE_MULT3 |
1710 | || TARGET_MAD" | |
cb923660 KR |
1711 | "* |
1712 | { | |
1713 | if (which_alternative == 1) | |
1714 | return \"mult\\t%1,%2\"; | |
1715 | if (TARGET_MAD) | |
1716 | return \"mul\\t%0,%1,%2\"; | |
1717 | return \"mult\\t%0,%1,%2\"; | |
1718 | }" | |
e9a25f70 | 1719 | [(set_attr "type" "imul") |
0ff83799 | 1720 | (set_attr "mode" "SI")]) |
e9a25f70 | 1721 | |
46299de9 ILT |
1722 | (define_insn "mulsi3_internal" |
1723 | [(set (match_operand:SI 0 "register_operand" "=l") | |
1724 | (mult:SI (match_operand:SI 1 "register_operand" "d") | |
1725 | (match_operand:SI 2 "register_operand" "d"))) | |
225b8835 ILT |
1726 | (clobber (match_scratch:SI 3 "=h")) |
1727 | (clobber (match_scratch:SI 4 "=a"))] | |
2bcb2ab3 | 1728 | "mips_cpu != PROCESSOR_R4000 || TARGET_MIPS16" |
46299de9 ILT |
1729 | "mult\\t%1,%2" |
1730 | [(set_attr "type" "imul") | |
0ff83799 | 1731 | (set_attr "mode" "SI")]) |
46299de9 ILT |
1732 | |
1733 | (define_insn "mulsi3_r4000" | |
1734 | [(set (match_operand:SI 0 "register_operand" "=d") | |
1735 | (mult:SI (match_operand:SI 1 "register_operand" "d") | |
1736 | (match_operand:SI 2 "register_operand" "d"))) | |
1737 | (clobber (match_scratch:SI 3 "=h")) | |
225b8835 ILT |
1738 | (clobber (match_scratch:SI 4 "=l")) |
1739 | (clobber (match_scratch:SI 5 "=a"))] | |
2bcb2ab3 | 1740 | "mips_cpu == PROCESSOR_R4000 && !TARGET_MIPS16" |
8ef30996 MM |
1741 | "* |
1742 | { | |
1743 | rtx xoperands[10]; | |
1744 | ||
1745 | xoperands[0] = operands[0]; | |
c5c76735 | 1746 | xoperands[1] = gen_rtx_REG (SImode, LO_REGNUM); |
8ef30996 MM |
1747 | |
1748 | output_asm_insn (\"mult\\t%1,%2\", operands); | |
bb621ad7 | 1749 | output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); |
8ef30996 MM |
1750 | return \"\"; |
1751 | }" | |
1752 | [(set_attr "type" "imul") | |
1753 | (set_attr "mode" "SI") | |
0ff83799 | 1754 | (set_attr "length" "12")]) ;; mult + mflo + delay |
8ef30996 | 1755 | |
e4f5c5d6 KR |
1756 | ;; Multiply-accumulate patterns |
1757 | ||
1758 | ;; For processors that can copy the output to a general register: | |
1759 | ;; | |
cb923660 KR |
1760 | ;; The all-d alternative is needed because the combiner will find this |
1761 | ;; pattern and then register alloc/reload will move registers around to | |
1762 | ;; make them fit, and we don't want to trigger unnecessary loads to LO. | |
e4f5c5d6 KR |
1763 | ;; |
1764 | ;; The last alternative should be made slightly less desirable, but adding | |
1765 | ;; "?" to the constraint is too strong, and causes values to be loaded into | |
1766 | ;; LO even when that's more costly. For now, using "*d" mostly does the | |
1767 | ;; trick. | |
cb923660 | 1768 | (define_insn "*mul_acc_si" |
e4f5c5d6 | 1769 | [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") |
cb923660 KR |
1770 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") |
1771 | (match_operand:SI 2 "register_operand" "d,d,d")) | |
e4f5c5d6 | 1772 | (match_operand:SI 3 "register_operand" "0,l,*d"))) |
cb923660 KR |
1773 | (clobber (match_scratch:SI 4 "=h,h,h")) |
1774 | (clobber (match_scratch:SI 5 "=X,3,l")) | |
1775 | (clobber (match_scratch:SI 6 "=a,a,a")) | |
1776 | (clobber (match_scratch:SI 7 "=X,X,d"))] | |
e4f5c5d6 KR |
1777 | "TARGET_MIPS3900 |
1778 | && !TARGET_MIPS16" | |
cb923660 KR |
1779 | "* |
1780 | { | |
e2fe6aba | 1781 | static const char *const madd[] = { \"madd\\t%1,%2\", \"madd\\t%0,%1,%2\" }; |
cb923660 KR |
1782 | if (which_alternative == 2) |
1783 | return \"#\"; | |
1784 | return madd[which_alternative]; | |
1785 | }" | |
1786 | [(set_attr "type" "imul,imul,multi") | |
053665d7 | 1787 | (set_attr "mode" "SI") |
0ff83799 | 1788 | (set_attr "length" "4,4,8")]) |
cb923660 | 1789 | |
e4f5c5d6 | 1790 | ;; Split the above insn if we failed to get LO allocated. |
cb923660 KR |
1791 | (define_split |
1792 | [(set (match_operand:SI 0 "register_operand" "") | |
1793 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") | |
1794 | (match_operand:SI 2 "register_operand" "")) | |
1795 | (match_operand:SI 3 "register_operand" ""))) | |
1796 | (clobber (match_scratch:SI 4 "")) | |
1797 | (clobber (match_scratch:SI 5 "")) | |
1798 | (clobber (match_scratch:SI 6 "")) | |
1799 | (clobber (match_scratch:SI 7 ""))] | |
1800 | "reload_completed && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[3]))" | |
1801 | [(parallel [(set (match_dup 7) | |
1802 | (mult:SI (match_dup 1) (match_dup 2))) | |
1803 | (clobber (match_dup 4)) | |
1804 | (clobber (match_dup 5)) | |
1805 | (clobber (match_dup 6))]) | |
1806 | (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 3)))] | |
1807 | "") | |
1808 | ||
1809 | (define_split | |
1810 | [(set (match_operand:SI 0 "register_operand" "") | |
1811 | (minus:SI (match_operand:SI 1 "register_operand" "") | |
1812 | (mult:SI (match_operand:SI 2 "register_operand" "") | |
1813 | (match_operand:SI 3 "register_operand" "")))) | |
1814 | (clobber (match_scratch:SI 4 "")) | |
1815 | (clobber (match_scratch:SI 5 "")) | |
1816 | (clobber (match_scratch:SI 6 "")) | |
1817 | (clobber (match_scratch:SI 7 ""))] | |
1818 | "reload_completed && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[1]))" | |
1819 | [(parallel [(set (match_dup 7) | |
1820 | (mult:SI (match_dup 2) (match_dup 3))) | |
1821 | (clobber (match_dup 4)) | |
1822 | (clobber (match_dup 5)) | |
1823 | (clobber (match_dup 6))]) | |
1824 | (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 7)))] | |
1825 | "") | |
053665d7 | 1826 | |
46299de9 ILT |
1827 | (define_expand "muldi3" |
1828 | [(set (match_operand:DI 0 "register_operand" "=l") | |
1908a152 | 1829 | (mult:DI (match_operand:DI 1 "se_register_operand" "d") |
46299de9 | 1830 | (match_operand:DI 2 "register_operand" "d"))) |
225b8835 ILT |
1831 | (clobber (match_scratch:DI 3 "=h")) |
1832 | (clobber (match_scratch:DI 4 "=a"))] | |
46299de9 | 1833 | "TARGET_64BIT" |
cb923660 | 1834 | |
46299de9 ILT |
1835 | " |
1836 | { | |
2bcb2ab3 | 1837 | if (GENERATE_MULT3 || mips_cpu == PROCESSOR_R4000 || TARGET_MIPS16) |
868e82ab | 1838 | emit_insn (gen_muldi3_internal2 (operands[0], operands[1], operands[2])); |
46299de9 | 1839 | else |
868e82ab | 1840 | emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2])); |
46299de9 ILT |
1841 | DONE; |
1842 | }") | |
8ef30996 | 1843 | |
1908a152 ILT |
1844 | ;; Don't accept both operands using se_register_operand, because if |
1845 | ;; both operands are sign extended we would prefer to use mult in the | |
1846 | ;; mulsidi3 pattern. Commutativity should permit either operand to be | |
1847 | ;; sign extended. | |
1848 | ||
46299de9 ILT |
1849 | (define_insn "muldi3_internal" |
1850 | [(set (match_operand:DI 0 "register_operand" "=l") | |
1908a152 | 1851 | (mult:DI (match_operand:DI 1 "se_register_operand" "d") |
46299de9 | 1852 | (match_operand:DI 2 "register_operand" "d"))) |
225b8835 ILT |
1853 | (clobber (match_scratch:DI 3 "=h")) |
1854 | (clobber (match_scratch:DI 4 "=a"))] | |
2bcb2ab3 | 1855 | "TARGET_64BIT && mips_cpu != PROCESSOR_R4000 && !TARGET_MIPS16" |
e7faa2f6 | 1856 | "dmult\\t%1,%2" |
8ef30996 | 1857 | [(set_attr "type" "imul") |
0ff83799 | 1858 | (set_attr "mode" "DI")]) |
8ef30996 | 1859 | |
868e82ab | 1860 | (define_insn "muldi3_internal2" |
bb621ad7 | 1861 | [(set (match_operand:DI 0 "register_operand" "=d") |
1908a152 | 1862 | (mult:DI (match_operand:DI 1 "se_register_operand" "d") |
bb621ad7 | 1863 | (match_operand:DI 2 "register_operand" "d"))) |
46299de9 | 1864 | (clobber (match_scratch:DI 3 "=h")) |
225b8835 ILT |
1865 | (clobber (match_scratch:DI 4 "=l")) |
1866 | (clobber (match_scratch:DI 5 "=a"))] | |
319f217e | 1867 | "TARGET_64BIT && (GENERATE_MULT3 || mips_cpu == PROCESSOR_R4000 || TARGET_MIPS16)" |
bb621ad7 JW |
1868 | "* |
1869 | { | |
868e82ab GK |
1870 | if (GENERATE_MULT3) |
1871 | output_asm_insn (\"dmult\\t%0,%1,%2\", operands); | |
1872 | else | |
1873 | { | |
c5c76735 | 1874 | rtx xoperands[10]; |
bb621ad7 | 1875 | |
c5c76735 JL |
1876 | xoperands[0] = operands[0]; |
1877 | xoperands[1] = gen_rtx_REG (DImode, LO_REGNUM); | |
bb621ad7 | 1878 | |
c5c76735 JL |
1879 | output_asm_insn (\"dmult\\t%1,%2\", operands); |
1880 | output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); | |
868e82ab | 1881 | } |
bb621ad7 JW |
1882 | return \"\"; |
1883 | }" | |
1884 | [(set_attr "type" "imul") | |
1885 | (set_attr "mode" "DI") | |
868e82ab GK |
1886 | (set (attr "length") |
1887 | (if_then_else (ne (symbol_ref "GENERATE_MULT3") (const_int 0)) | |
0ff83799 MM |
1888 | (const_int 4) |
1889 | (const_int 12)))]) ;; mult + mflo + delay | |
bb621ad7 | 1890 | |
bb621ad7 JW |
1891 | ;; ??? We could define a mulditi3 pattern when TARGET_64BIT. |
1892 | ||
225b8835 | 1893 | (define_expand "mulsidi3" |
46299de9 | 1894 | [(set (match_operand:DI 0 "register_operand" "=x") |
8ef30996 | 1895 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) |
46299de9 | 1896 | (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] |
225b8835 ILT |
1897 | "" |
1898 | " | |
1899 | { | |
cb923660 | 1900 | rtx dummy = gen_rtx (SIGN_EXTEND, DImode, const0_rtx); |
225b8835 | 1901 | if (TARGET_64BIT) |
cb923660 KR |
1902 | emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2], |
1903 | dummy, dummy)); | |
225b8835 | 1904 | else |
cb923660 KR |
1905 | emit_insn (gen_mulsidi3_internal (operands[0], operands[1], operands[2], |
1906 | dummy, dummy)); | |
225b8835 ILT |
1907 | DONE; |
1908 | }") | |
1909 | ||
225b8835 | 1910 | (define_expand "umulsidi3" |
46299de9 | 1911 | [(set (match_operand:DI 0 "register_operand" "=x") |
8ef30996 | 1912 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) |
46299de9 | 1913 | (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] |
225b8835 ILT |
1914 | "" |
1915 | " | |
1916 | { | |
cb923660 | 1917 | rtx dummy = gen_rtx (ZERO_EXTEND, DImode, const0_rtx); |
225b8835 | 1918 | if (TARGET_64BIT) |
cb923660 KR |
1919 | emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2], |
1920 | dummy, dummy)); | |
225b8835 | 1921 | else |
cb923660 KR |
1922 | emit_insn (gen_mulsidi3_internal (operands[0], operands[1], operands[2], |
1923 | dummy, dummy)); | |
225b8835 ILT |
1924 | DONE; |
1925 | }") | |
1926 | ||
cb923660 | 1927 | (define_insn "mulsidi3_internal" |
225b8835 | 1928 | [(set (match_operand:DI 0 "register_operand" "=x") |
cb923660 KR |
1929 | (mult:DI (match_operator:DI 3 "extend_operator" |
1930 | [(match_operand:SI 1 "register_operand" "d")]) | |
1931 | (match_operator:DI 4 "extend_operator" | |
1932 | [(match_operand:SI 2 "register_operand" "d")]))) | |
1933 | (clobber (match_scratch:SI 5 "=a"))] | |
1934 | "!TARGET_64BIT && GET_CODE (operands[3]) == GET_CODE (operands[4])" | |
1935 | "* | |
1936 | { | |
1937 | if (GET_CODE (operands[3]) == SIGN_EXTEND) | |
1938 | return \"mult\\t%1,%2\"; | |
1939 | return \"multu\\t%1,%2\"; | |
1940 | }" | |
8ef30996 | 1941 | [(set_attr "type" "imul") |
0ff83799 | 1942 | (set_attr "mode" "SI")]) |
8ef30996 | 1943 | |
cb923660 | 1944 | (define_insn "mulsidi3_64bit" |
225b8835 | 1945 | [(set (match_operand:DI 0 "register_operand" "=a") |
cb923660 KR |
1946 | (mult:DI (match_operator:DI 3 "extend_operator" |
1947 | [(match_operand:SI 1 "register_operand" "d")]) | |
1948 | (match_operator:DI 4 "extend_operator" | |
1949 | [(match_operand:SI 2 "register_operand" "d")]))) | |
1950 | (clobber (match_scratch:DI 5 "=l")) | |
1951 | (clobber (match_scratch:DI 6 "=h"))] | |
1952 | "TARGET_64BIT && GET_CODE (operands[3]) == GET_CODE (operands[4])" | |
1953 | "* | |
1954 | { | |
1955 | if (GET_CODE (operands[3]) == SIGN_EXTEND) | |
1956 | return \"mult\\t%1,%2\"; | |
1957 | return \"multu\\t%1,%2\"; | |
1958 | }" | |
225b8835 | 1959 | [(set_attr "type" "imul") |
0ff83799 | 1960 | (set_attr "mode" "SI")]) |
225b8835 | 1961 | |
cb923660 KR |
1962 | ;; _highpart patterns |
1963 | (define_expand "smulsi3_highpart" | |
1964 | [(set (match_operand:SI 0 "register_operand" "=h") | |
1965 | (truncate:SI | |
1966 | (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1967 | (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))) | |
1968 | (const_int 32))))] | |
1969 | "" | |
1970 | " | |
1971 | { | |
1972 | rtx dummy = gen_rtx (SIGN_EXTEND, DImode, const0_rtx); | |
1973 | rtx dummy2 = gen_rtx_LSHIFTRT (DImode, const0_rtx, const0_rtx); | |
e4f5c5d6 | 1974 | #ifndef NO_MD_PROTOTYPES |
f6da8bc3 | 1975 | rtx (*genfn) PARAMS ((rtx, rtx, rtx, rtx, rtx, rtx)); |
e4f5c5d6 KR |
1976 | #else |
1977 | rtx (*genfn) (); | |
1978 | #endif | |
1979 | genfn = gen_xmulsi3_highpart_internal; | |
cb923660 KR |
1980 | emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy, |
1981 | dummy, dummy2)); | |
1982 | DONE; | |
1983 | }") | |
1984 | ||
1985 | (define_expand "umulsi3_highpart" | |
46299de9 | 1986 | [(set (match_operand:SI 0 "register_operand" "=h") |
903df3fe JW |
1987 | (truncate:SI |
1988 | (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) | |
1989 | (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))) | |
cb923660 | 1990 | (const_int 32))))] |
903df3fe | 1991 | "" |
cb923660 KR |
1992 | " |
1993 | { | |
1994 | rtx dummy = gen_rtx (ZERO_EXTEND, DImode, const0_rtx); | |
1995 | rtx dummy2 = gen_rtx_LSHIFTRT (DImode, const0_rtx, const0_rtx); | |
e4f5c5d6 | 1996 | #ifndef NO_MD_PROTOTYPES |
f6da8bc3 | 1997 | rtx (*genfn) PARAMS ((rtx, rtx, rtx, rtx, rtx, rtx)); |
e4f5c5d6 KR |
1998 | #else |
1999 | rtx (*genfn) (); | |
2000 | #endif | |
2001 | genfn = gen_xmulsi3_highpart_internal; | |
cb923660 KR |
2002 | emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy, |
2003 | dummy, dummy2)); | |
2004 | DONE; | |
2005 | }") | |
2006 | ||
2007 | (define_insn "xmulsi3_highpart_internal" | |
2008 | [(set (match_operand:SI 0 "register_operand" "=h") | |
2009 | (truncate:SI | |
2010 | (match_operator:DI 5 "highpart_shift_operator" | |
2011 | [(mult:DI (match_operator:DI 3 "extend_operator" | |
2012 | [(match_operand:SI 1 "register_operand" "d")]) | |
2013 | (match_operator:DI 4 "extend_operator" | |
2014 | [(match_operand:SI 2 "register_operand" "d")])) | |
2015 | (const_int 32)]))) | |
2016 | (clobber (match_scratch:SI 6 "=l")) | |
2017 | (clobber (match_scratch:SI 7 "=a"))] | |
2018 | "GET_CODE (operands[3]) == GET_CODE (operands[4])" | |
2019 | "* | |
2020 | { | |
2021 | if (GET_CODE (operands[3]) == SIGN_EXTEND) | |
2022 | return \"mult\\t%1,%2\"; | |
2023 | else | |
2024 | return \"multu\\t%1,%2\"; | |
2025 | }" | |
903df3fe | 2026 | [(set_attr "type" "imul") |
0ff83799 | 2027 | (set_attr "mode" "SI")]) |
48199e32 JW |
2028 | |
2029 | (define_insn "smuldi3_highpart" | |
46299de9 | 2030 | [(set (match_operand:DI 0 "register_operand" "=h") |
48199e32 | 2031 | (truncate:DI |
1908a152 ILT |
2032 | (lshiftrt:TI (mult:TI (sign_extend:TI (match_operand:DI 1 "se_register_operand" "d")) |
2033 | (sign_extend:TI (match_operand:DI 2 "se_register_operand" "d"))) | |
48199e32 | 2034 | (const_int 64)))) |
225b8835 ILT |
2035 | (clobber (match_scratch:DI 3 "=l")) |
2036 | (clobber (match_scratch:DI 4 "=a"))] | |
48199e32 | 2037 | "TARGET_64BIT" |
46299de9 | 2038 | "dmult\\t%1,%2" |
48199e32 | 2039 | [(set_attr "type" "imul") |
0ff83799 | 2040 | (set_attr "mode" "DI")]) |
48199e32 JW |
2041 | |
2042 | (define_insn "umuldi3_highpart" | |
46299de9 | 2043 | [(set (match_operand:DI 0 "register_operand" "=h") |
48199e32 | 2044 | (truncate:DI |
1908a152 ILT |
2045 | (lshiftrt:TI (mult:TI (zero_extend:TI (match_operand:DI 1 "se_register_operand" "d")) |
2046 | (zero_extend:TI (match_operand:DI 2 "se_register_operand" "d"))) | |
48199e32 | 2047 | (const_int 64)))) |
225b8835 ILT |
2048 | (clobber (match_scratch:DI 3 "=l")) |
2049 | (clobber (match_scratch:DI 4 "=a"))] | |
48199e32 | 2050 | "TARGET_64BIT" |
46299de9 | 2051 | "dmultu\\t%1,%2" |
48199e32 | 2052 | [(set_attr "type" "imul") |
0ff83799 | 2053 | (set_attr "mode" "DI")]) |
48199e32 | 2054 | |
46299de9 ILT |
2055 | ;; The R4650 supports a 32 bit multiply/ 64 bit accumulate |
2056 | ;; instruction. The HI/LO registers are used as a 64 bit accumulator. | |
2057 | ||
2058 | (define_insn "madsi" | |
2059 | [(set (match_operand:SI 0 "register_operand" "+l") | |
2060 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") | |
2061 | (match_operand:SI 2 "register_operand" "d")) | |
2062 | (match_dup 0))) | |
225b8835 ILT |
2063 | (clobber (match_scratch:SI 3 "=h")) |
2064 | (clobber (match_scratch:SI 4 "=a"))] | |
cb923660 | 2065 | "TARGET_MAD" |
225b8835 ILT |
2066 | "mad\\t%1,%2" |
2067 | [(set_attr "type" "imul") | |
0ff83799 | 2068 | (set_attr "mode" "SI")]) |
225b8835 | 2069 | |
cb923660 | 2070 | (define_insn "*mul_acc_di" |
46299de9 | 2071 | [(set (match_operand:DI 0 "register_operand" "+x") |
cb923660 KR |
2072 | (plus:DI (mult:DI (match_operator:DI 3 "extend_operator" |
2073 | [(match_operand:SI 1 "register_operand" "d")]) | |
e4f5c5d6 | 2074 | (match_operator:DI 4 "extend_operator" |
cb923660 | 2075 | [(match_operand:SI 2 "register_operand" "d")])) |
225b8835 | 2076 | (match_dup 0))) |
e4f5c5d6 KR |
2077 | (clobber (match_scratch:SI 5 "=a"))] |
2078 | "TARGET_MAD | |
2079 | && ! TARGET_64BIT | |
2080 | && GET_CODE (operands[3]) == GET_CODE (operands[4])" | |
cb923660 KR |
2081 | "* |
2082 | { | |
2083 | if (GET_CODE (operands[3]) == SIGN_EXTEND) | |
2084 | return \"mad\\t%1,%2\"; | |
2085 | else | |
2086 | return \"madu\\t%1,%2\"; | |
2087 | }" | |
46299de9 | 2088 | [(set_attr "type" "imul") |
0ff83799 | 2089 | (set_attr "mode" "SI")]) |
e19ff60f | 2090 | |
cb923660 | 2091 | (define_insn "*mul_acc_64bit_di" |
225b8835 | 2092 | [(set (match_operand:DI 0 "register_operand" "+a") |
cb923660 KR |
2093 | (plus:DI (mult:DI (match_operator:DI 3 "extend_operator" |
2094 | [(match_operand:SI 1 "register_operand" "d")]) | |
e4f5c5d6 | 2095 | (match_operator:DI 4 "extend_operator" |
cb923660 | 2096 | [(match_operand:SI 2 "register_operand" "d")])) |
225b8835 | 2097 | (match_dup 0))) |
e4f5c5d6 KR |
2098 | (clobber (match_scratch:SI 5 "=h")) |
2099 | (clobber (match_scratch:SI 6 "=l"))] | |
2100 | "TARGET_MAD | |
2101 | && TARGET_64BIT | |
2102 | && GET_CODE (operands[3]) == GET_CODE (operands[4])" | |
cb923660 KR |
2103 | "* |
2104 | { | |
2105 | if (GET_CODE (operands[3]) == SIGN_EXTEND) | |
2106 | return \"mad\\t%1,%2\"; | |
2107 | else | |
2108 | return \"madu\\t%1,%2\"; | |
2109 | }" | |
e9a25f70 | 2110 | [(set_attr "type" "imul") |
0ff83799 | 2111 | (set_attr "mode" "SI")]) |
e9a25f70 | 2112 | |
e19ff60f JW |
2113 | ;; Floating point multiply accumulate instructions. |
2114 | ||
2115 | (define_insn "" | |
2116 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2117 | (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f") | |
2118 | (match_operand:DF 2 "register_operand" "f")) | |
2119 | (match_operand:DF 3 "register_operand" "f")))] | |
1d5d552e | 2120 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
e19ff60f JW |
2121 | "madd.d\\t%0,%3,%1,%2" |
2122 | [(set_attr "type" "fmadd") | |
0ff83799 | 2123 | (set_attr "mode" "DF")]) |
e19ff60f JW |
2124 | |
2125 | (define_insn "" | |
2126 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2127 | (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "f") | |
2128 | (match_operand:SF 2 "register_operand" "f")) | |
2129 | (match_operand:SF 3 "register_operand" "f")))] | |
1d5d552e | 2130 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT" |
e19ff60f JW |
2131 | "madd.s\\t%0,%3,%1,%2" |
2132 | [(set_attr "type" "fmadd") | |
0ff83799 | 2133 | (set_attr "mode" "SF")]) |
e19ff60f JW |
2134 | |
2135 | (define_insn "" | |
2136 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2137 | (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "f") | |
2138 | (match_operand:DF 2 "register_operand" "f")) | |
2139 | (match_operand:DF 3 "register_operand" "f")))] | |
1d5d552e | 2140 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
e19ff60f JW |
2141 | "msub.d\\t%0,%3,%1,%2" |
2142 | [(set_attr "type" "fmadd") | |
0ff83799 | 2143 | (set_attr "mode" "DF")]) |
e19ff60f JW |
2144 | |
2145 | (define_insn "" | |
2146 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2147 | (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "f") | |
2148 | (match_operand:SF 2 "register_operand" "f")) | |
2149 | (match_operand:SF 3 "register_operand" "f")))] | |
2150 | ||
1d5d552e | 2151 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT" |
e19ff60f JW |
2152 | "msub.s\\t%0,%3,%1,%2" |
2153 | [(set_attr "type" "fmadd") | |
0ff83799 | 2154 | (set_attr "mode" "SF")]) |
e19ff60f JW |
2155 | |
2156 | (define_insn "" | |
2157 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2158 | (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f") | |
2159 | (match_operand:DF 2 "register_operand" "f")) | |
2160 | (match_operand:DF 3 "register_operand" "f"))))] | |
1d5d552e | 2161 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
e19ff60f JW |
2162 | "nmadd.d\\t%0,%3,%1,%2" |
2163 | [(set_attr "type" "fmadd") | |
0ff83799 | 2164 | (set_attr "mode" "DF")]) |
e19ff60f JW |
2165 | |
2166 | (define_insn "" | |
2167 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2168 | (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "f") | |
2169 | (match_operand:SF 2 "register_operand" "f")) | |
2170 | (match_operand:SF 3 "register_operand" "f"))))] | |
1d5d552e | 2171 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT" |
e19ff60f JW |
2172 | "nmadd.s\\t%0,%3,%1,%2" |
2173 | [(set_attr "type" "fmadd") | |
0ff83799 | 2174 | (set_attr "mode" "SF")]) |
e19ff60f JW |
2175 | |
2176 | (define_insn "" | |
2177 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2178 | (minus:DF (match_operand:DF 1 "register_operand" "f") | |
2179 | (mult:DF (match_operand:DF 2 "register_operand" "f") | |
2180 | (match_operand:DF 3 "register_operand" "f"))))] | |
1d5d552e | 2181 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
e19ff60f JW |
2182 | "nmsub.d\\t%0,%1,%2,%3" |
2183 | [(set_attr "type" "fmadd") | |
0ff83799 | 2184 | (set_attr "mode" "DF")]) |
e19ff60f JW |
2185 | |
2186 | (define_insn "" | |
2187 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2188 | (minus:SF (match_operand:SF 1 "register_operand" "f") | |
2189 | (mult:SF (match_operand:SF 2 "register_operand" "f") | |
2190 | (match_operand:SF 3 "register_operand" "f"))))] | |
1d5d552e | 2191 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT" |
e19ff60f JW |
2192 | "nmsub.s\\t%0,%1,%2,%3" |
2193 | [(set_attr "type" "fmadd") | |
0ff83799 | 2194 | (set_attr "mode" "SF")]) |
8ef30996 MM |
2195 | \f |
2196 | ;; | |
2197 | ;; .................... | |
2198 | ;; | |
2199 | ;; DIVISION and REMAINDER | |
2200 | ;; | |
2201 | ;; .................... | |
2202 | ;; | |
2203 | ||
2204 | (define_insn "divdf3" | |
2205 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2206 | (div:DF (match_operand:DF 1 "register_operand" "f") | |
2207 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 2208 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
2209 | "div.d\\t%0,%1,%2" |
2210 | [(set_attr "type" "fdiv") | |
0ff83799 | 2211 | (set_attr "mode" "DF")]) |
8ef30996 MM |
2212 | |
2213 | (define_insn "divsf3" | |
2214 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2215 | (div:SF (match_operand:SF 1 "register_operand" "f") | |
2216 | (match_operand:SF 2 "register_operand" "f")))] | |
2217 | "TARGET_HARD_FLOAT" | |
2218 | "div.s\\t%0,%1,%2" | |
2219 | [(set_attr "type" "fdiv") | |
0ff83799 | 2220 | (set_attr "mode" "SF")]) |
8ef30996 | 2221 | |
b8eb88d0 ILT |
2222 | (define_insn "" |
2223 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2224 | (div:DF (match_operand:DF 1 "const_float_1_operand" "") | |
2225 | (match_operand:DF 2 "register_operand" "f")))] | |
de6c5979 | 2226 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations" |
b8eb88d0 ILT |
2227 | "recip.d\\t%0,%2" |
2228 | [(set_attr "type" "fdiv") | |
0ff83799 | 2229 | (set_attr "mode" "DF")]) |
b8eb88d0 ILT |
2230 | |
2231 | (define_insn "" | |
2232 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2233 | (div:SF (match_operand:SF 1 "const_float_1_operand" "") | |
2234 | (match_operand:SF 2 "register_operand" "f")))] | |
de6c5979 | 2235 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations" |
b8eb88d0 ILT |
2236 | "recip.s\\t%0,%2" |
2237 | [(set_attr "type" "fdiv") | |
0ff83799 | 2238 | (set_attr "mode" "SF")]) |
b8eb88d0 | 2239 | |
8ef30996 MM |
2240 | ;; If optimizing, prefer the divmod functions over separate div and |
2241 | ;; mod functions, since this will allow using one instruction for both | |
2242 | ;; the quotient and remainder. At present, the divmod is not moved out | |
2243 | ;; of loops if it is constant within the loop, so allow -mdebugc to | |
2244 | ;; use the old method of doing things. | |
2245 | ||
2246 | ;; 64 is the multiply/divide hi register | |
2247 | ;; 65 is the multiply/divide lo register | |
2248 | ||
bb621ad7 JW |
2249 | ;; ??? We can't accept constants here, because the MIPS assembler will replace |
2250 | ;; a divide by power of 2 with a shift, and then the remainder is no longer | |
2251 | ;; available. | |
2252 | ||
08c2951c | 2253 | (define_expand "divmodsi4" |
70252580 MM |
2254 | [(set (match_operand:SI 0 "register_operand" "=d") |
2255 | (div:SI (match_operand:SI 1 "register_operand" "d") | |
2256 | (match_operand:SI 2 "register_operand" "d"))) | |
2257 | (set (match_operand:SI 3 "register_operand" "=d") | |
2258 | (mod:SI (match_dup 1) | |
2259 | (match_dup 2))) | |
46299de9 | 2260 | (clobber (match_scratch:SI 4 "=l")) |
225b8835 ILT |
2261 | (clobber (match_scratch:SI 5 "=h")) |
2262 | (clobber (match_scratch:SI 6 "=a"))] | |
34b650b3 | 2263 | "optimize" |
08c2951c | 2264 | " |
8ef30996 | 2265 | { |
08c2951c SC |
2266 | emit_insn (gen_divmodsi4_internal (operands[0], operands[1], operands[2], |
2267 | operands[3])); | |
2268 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2269 | { | |
2270 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2271 | GEN_INT (0), |
08c2951c SC |
2272 | GEN_INT (0x7))); |
2273 | } | |
2274 | if (TARGET_CHECK_RANGE_DIV) | |
2275 | { | |
2276 | emit_insn (gen_div_trap (operands[2], | |
2277 | copy_to_mode_reg (SImode, GEN_INT (-1)), | |
2278 | GEN_INT (0x6))); | |
2279 | emit_insn (gen_div_trap (operands[2], | |
3a6ee9f4 | 2280 | copy_to_mode_reg (SImode, GEN_INT (BITMASK_HIGH)), |
08c2951c SC |
2281 | GEN_INT (0x6))); |
2282 | } | |
2283 | ||
2284 | DONE; | |
2285 | }") | |
8ef30996 | 2286 | |
08c2951c SC |
2287 | (define_insn "divmodsi4_internal" |
2288 | [(set (match_operand:SI 0 "register_operand" "=l") | |
2289 | (div:SI (match_operand:SI 1 "register_operand" "d") | |
2290 | (match_operand:SI 2 "register_operand" "d"))) | |
2291 | (set (match_operand:SI 3 "register_operand" "=h") | |
2292 | (mod:SI (match_dup 1) | |
2293 | (match_dup 2))) | |
c77e04ae | 2294 | (clobber (match_scratch:SI 4 "=a"))] |
08c2951c SC |
2295 | "optimize" |
2296 | "div\\t$0,%1,%2" | |
8ef30996 | 2297 | [(set_attr "type" "idiv") |
0ff83799 | 2298 | (set_attr "mode" "SI")]) |
bb621ad7 | 2299 | |
08c2951c | 2300 | (define_expand "divmoddi4" |
bb621ad7 | 2301 | [(set (match_operand:DI 0 "register_operand" "=d") |
1908a152 ILT |
2302 | (div:DI (match_operand:DI 1 "se_register_operand" "d") |
2303 | (match_operand:DI 2 "se_register_operand" "d"))) | |
bb621ad7 JW |
2304 | (set (match_operand:DI 3 "register_operand" "=d") |
2305 | (mod:DI (match_dup 1) | |
2306 | (match_dup 2))) | |
46299de9 | 2307 | (clobber (match_scratch:DI 4 "=l")) |
225b8835 ILT |
2308 | (clobber (match_scratch:DI 5 "=h")) |
2309 | (clobber (match_scratch:DI 6 "=a"))] | |
bb621ad7 | 2310 | "TARGET_64BIT && optimize" |
08c2951c | 2311 | " |
bb621ad7 | 2312 | { |
08c2951c SC |
2313 | emit_insn (gen_divmoddi4_internal (operands[0], operands[1], operands[2], |
2314 | operands[3])); | |
2315 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2316 | { | |
2317 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2318 | GEN_INT (0), |
08c2951c SC |
2319 | GEN_INT (0x7))); |
2320 | } | |
2321 | if (TARGET_CHECK_RANGE_DIV) | |
2322 | { | |
2323 | emit_insn (gen_div_trap (operands[2], | |
2324 | copy_to_mode_reg (DImode, GEN_INT (-1)), | |
2325 | GEN_INT (0x6))); | |
2326 | emit_insn (gen_div_trap (operands[2], | |
3a6ee9f4 | 2327 | copy_to_mode_reg (DImode, GEN_INT (BITMASK_HIGH)), |
08c2951c SC |
2328 | GEN_INT (0x6))); |
2329 | } | |
2330 | ||
2331 | DONE; | |
2332 | }") | |
bb621ad7 | 2333 | |
08c2951c SC |
2334 | (define_insn "divmoddi4_internal" |
2335 | [(set (match_operand:DI 0 "register_operand" "=l") | |
2336 | (div:DI (match_operand:DI 1 "se_register_operand" "d") | |
2337 | (match_operand:DI 2 "se_register_operand" "d"))) | |
2338 | (set (match_operand:DI 3 "register_operand" "=h") | |
2339 | (mod:DI (match_dup 1) | |
2340 | (match_dup 2))) | |
c77e04ae | 2341 | (clobber (match_scratch:DI 4 "=a"))] |
08c2951c SC |
2342 | "TARGET_64BIT && optimize" |
2343 | "ddiv\\t$0,%1,%2" | |
bb621ad7 | 2344 | [(set_attr "type" "idiv") |
0ff83799 | 2345 | (set_attr "mode" "SI")]) |
8ef30996 | 2346 | |
08c2951c | 2347 | (define_expand "udivmodsi4" |
70252580 MM |
2348 | [(set (match_operand:SI 0 "register_operand" "=d") |
2349 | (udiv:SI (match_operand:SI 1 "register_operand" "d") | |
2350 | (match_operand:SI 2 "register_operand" "d"))) | |
2351 | (set (match_operand:SI 3 "register_operand" "=d") | |
2352 | (umod:SI (match_dup 1) | |
2353 | (match_dup 2))) | |
46299de9 | 2354 | (clobber (match_scratch:SI 4 "=l")) |
225b8835 ILT |
2355 | (clobber (match_scratch:SI 5 "=h")) |
2356 | (clobber (match_scratch:SI 6 "=a"))] | |
34b650b3 | 2357 | "optimize" |
08c2951c | 2358 | " |
8ef30996 | 2359 | { |
08c2951c SC |
2360 | emit_insn (gen_udivmodsi4_internal (operands[0], operands[1], operands[2], |
2361 | operands[3])); | |
2362 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2363 | { | |
2364 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2365 | GEN_INT (0), |
08c2951c SC |
2366 | GEN_INT (0x7))); |
2367 | } | |
2368 | ||
2369 | DONE; | |
2370 | }") | |
8ef30996 | 2371 | |
08c2951c SC |
2372 | (define_insn "udivmodsi4_internal" |
2373 | [(set (match_operand:SI 0 "register_operand" "=l") | |
2374 | (udiv:SI (match_operand:SI 1 "register_operand" "d") | |
2375 | (match_operand:SI 2 "register_operand" "d"))) | |
2376 | (set (match_operand:SI 3 "register_operand" "=h") | |
2377 | (umod:SI (match_dup 1) | |
2378 | (match_dup 2))) | |
c77e04ae | 2379 | (clobber (match_scratch:SI 4 "=a"))] |
08c2951c SC |
2380 | "optimize" |
2381 | "divu\\t$0,%1,%2" | |
8ef30996 | 2382 | [(set_attr "type" "idiv") |
0ff83799 | 2383 | (set_attr "mode" "SI")]) |
bb621ad7 | 2384 | |
08c2951c | 2385 | (define_expand "udivmoddi4" |
bb621ad7 | 2386 | [(set (match_operand:DI 0 "register_operand" "=d") |
1908a152 ILT |
2387 | (udiv:DI (match_operand:DI 1 "se_register_operand" "d") |
2388 | (match_operand:DI 2 "se_register_operand" "d"))) | |
bb621ad7 JW |
2389 | (set (match_operand:DI 3 "register_operand" "=d") |
2390 | (umod:DI (match_dup 1) | |
2391 | (match_dup 2))) | |
46299de9 | 2392 | (clobber (match_scratch:DI 4 "=l")) |
225b8835 ILT |
2393 | (clobber (match_scratch:DI 5 "=h")) |
2394 | (clobber (match_scratch:DI 6 "=a"))] | |
bb621ad7 | 2395 | "TARGET_64BIT && optimize" |
08c2951c | 2396 | " |
bb621ad7 | 2397 | { |
08c2951c SC |
2398 | emit_insn (gen_udivmoddi4_internal (operands[0], operands[1], operands[2], |
2399 | operands[3])); | |
2400 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2401 | { | |
2402 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2403 | GEN_INT (0), |
08c2951c SC |
2404 | GEN_INT (0x7))); |
2405 | } | |
2406 | ||
2407 | DONE; | |
2408 | }") | |
bb621ad7 | 2409 | |
08c2951c SC |
2410 | (define_insn "udivmoddi4_internal" |
2411 | [(set (match_operand:DI 0 "register_operand" "=l") | |
2412 | (udiv:DI (match_operand:DI 1 "se_register_operand" "d") | |
2413 | (match_operand:DI 2 "se_register_operand" "d"))) | |
2414 | (set (match_operand:DI 3 "register_operand" "=h") | |
2415 | (umod:DI (match_dup 1) | |
2416 | (match_dup 2))) | |
c77e04ae | 2417 | (clobber (match_scratch:DI 4 "=a"))] |
08c2951c SC |
2418 | "TARGET_64BIT && optimize" |
2419 | "ddivu\\t$0,%1,%2" | |
2420 | [(set_attr "type" "idiv") | |
0ff83799 | 2421 | (set_attr "mode" "SI")]) |
08c2951c SC |
2422 | |
2423 | ;; Division trap | |
bb621ad7 | 2424 | |
aa7ecb4a | 2425 | (define_expand "div_trap" |
08c2951c | 2426 | [(trap_if (eq (match_operand 0 "register_operand" "d") |
def72bd2 | 2427 | (match_operand 1 "true_reg_or_0_operand" "dJ")) |
08c2951c SC |
2428 | (match_operand 2 "immediate_operand" ""))] |
2429 | "" | |
aa7ecb4a GRK |
2430 | " |
2431 | { | |
2432 | if (TARGET_MIPS16) | |
2433 | emit_insn (gen_div_trap_mips16 (operands[0],operands[1],operands[2])); | |
2434 | else | |
2435 | emit_insn (gen_div_trap_normal (operands[0],operands[1],operands[2])); | |
2436 | DONE; | |
2437 | }") | |
2438 | ||
2439 | (define_insn "div_trap_normal" | |
8f8b5612 GK |
2440 | [(trap_if (eq (match_operand 0 "register_operand" "d,d") |
2441 | (match_operand 1 "true_reg_or_0_operand" "d,J")) | |
aa7ecb4a GRK |
2442 | (match_operand 2 "immediate_operand" ""))] |
2443 | "!TARGET_MIPS16" | |
08c2951c SC |
2444 | "* |
2445 | { | |
2446 | rtx link; | |
2447 | int have_dep_anti = 0; | |
2448 | ||
2449 | /* For divmod if one division is not needed then we don't need an extra | |
2450 | divide by zero trap, which is anti dependent on previous trap */ | |
2451 | for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) | |
2452 | ||
2453 | if ((int) REG_DEP_ANTI == (int) REG_NOTE_KIND (link) | |
487f99d2 | 2454 | && GET_CODE (XEXP (link, 0)) == INSN |
08c2951c | 2455 | && GET_CODE (PATTERN (XEXP (link, 0))) == TRAP_IF |
8f8b5612 | 2456 | && which_alternative == 1) |
08c2951c SC |
2457 | have_dep_anti = 1; |
2458 | if (! have_dep_anti) | |
b151501e JL |
2459 | { |
2460 | if (GENERATE_BRANCHLIKELY) | |
2461 | { | |
8f8b5612 | 2462 | if (which_alternative == 1) |
efa3896a | 2463 | return \"%(beql\\t%0,$0,1f\\n\\tbreak\\t%2\\n%~1:%)\"; |
b151501e | 2464 | else |
efa3896a | 2465 | return \"%(beql\\t%0,%1,1f\\n\\tbreak\\t%2\\n%~1:%)\"; |
b151501e JL |
2466 | } |
2467 | else | |
2468 | { | |
8f8b5612 | 2469 | if (which_alternative == 1) |
efa3896a | 2470 | return \"%(bne\\t%0,$0,1f\\n\\tnop\\n\\tbreak\\t%2\\n%~1:%)\"; |
b151501e | 2471 | else |
efa3896a | 2472 | return \"%(bne\\t%0,%1,1f\\n\\tnop\\n\\tbreak\\t%2\\n%~1:%)\"; |
b151501e JL |
2473 | } |
2474 | } | |
8da31fc1 | 2475 | return \"\"; |
bb621ad7 | 2476 | }" |
08c2951c | 2477 | [(set_attr "type" "unknown") |
0ff83799 | 2478 | (set_attr "length" "12")]) |
aa7ecb4a GRK |
2479 | |
2480 | ||
2481 | ;; The mips16 bne insns is a macro which uses reg 24 as an intermediate. | |
2482 | ||
2483 | (define_insn "div_trap_mips16" | |
8f8b5612 GK |
2484 | [(trap_if (eq (match_operand 0 "register_operand" "d,d") |
2485 | (match_operand 1 "true_reg_or_0_operand" "d,J")) | |
aa7ecb4a GRK |
2486 | (match_operand 2 "immediate_operand" "")) |
2487 | (clobber (reg:SI 24))] | |
2488 | "TARGET_MIPS16" | |
2489 | "* | |
2490 | { | |
2491 | rtx link; | |
2492 | int have_dep_anti = 0; | |
2493 | ||
2494 | /* For divmod if one division is not needed then we don't need an extra | |
2495 | divide by zero trap, which is anti dependent on previous trap */ | |
2496 | for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) | |
2497 | ||
2498 | if ((int) REG_DEP_ANTI == (int) REG_NOTE_KIND (link) | |
487f99d2 | 2499 | && GET_CODE (XEXP (link, 0)) == INSN |
aa7ecb4a | 2500 | && GET_CODE (PATTERN (XEXP (link, 0))) == TRAP_IF |
8f8b5612 | 2501 | && which_alternative == 1) |
aa7ecb4a GRK |
2502 | have_dep_anti = 1; |
2503 | if (! have_dep_anti) | |
2504 | { | |
6ebec6ee | 2505 | /* No branch delay slots on mips16. */ |
8f8b5612 | 2506 | if (which_alternative == 1) |
efa3896a | 2507 | return \"%(bnez\\t%0,1f\\n\\tbreak\\t%2\\n%~1:%)\"; |
aa7ecb4a | 2508 | else |
efa3896a | 2509 | return \"%(bne\\t%0,%1,1f\\n\\tbreak\\t%2\\n%~1:%)\"; |
aa7ecb4a GRK |
2510 | } |
2511 | return \"\"; | |
2512 | }" | |
2513 | [(set_attr "type" "unknown") | |
0ff83799 | 2514 | (set_attr "length" "12")]) |
8ef30996 | 2515 | |
7e07e3ba | 2516 | (define_expand "divsi3" |
08c2951c | 2517 | [(set (match_operand:SI 0 "register_operand" "=l") |
8ef30996 | 2518 | (div:SI (match_operand:SI 1 "register_operand" "d") |
08c2951c SC |
2519 | (match_operand:SI 2 "register_operand" "d"))) |
2520 | (clobber (match_scratch:SI 3 "=h")) | |
2521 | (clobber (match_scratch:SI 4 "=a"))] | |
34b650b3 | 2522 | "!optimize" |
7e07e3ba GK |
2523 | " |
2524 | { | |
08c2951c SC |
2525 | emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2])); |
2526 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2527 | { | |
2528 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2529 | GEN_INT (0), |
08c2951c SC |
2530 | GEN_INT (0x7))); |
2531 | } | |
2532 | if (TARGET_CHECK_RANGE_DIV) | |
2533 | { | |
2534 | emit_insn (gen_div_trap (operands[2], | |
2535 | copy_to_mode_reg (SImode, GEN_INT (-1)), | |
2536 | GEN_INT (0x6))); | |
2537 | emit_insn (gen_div_trap (operands[2], | |
3a6ee9f4 | 2538 | copy_to_mode_reg (SImode, GEN_INT (BITMASK_HIGH)), |
08c2951c SC |
2539 | GEN_INT (0x6))); |
2540 | } | |
2541 | ||
2542 | DONE; | |
7e07e3ba GK |
2543 | }") |
2544 | ||
2545 | (define_insn "divsi3_internal" | |
08c2951c | 2546 | [(set (match_operand:SI 0 "register_operand" "=l") |
7e07e3ba | 2547 | (div:SI (match_operand:SI 1 "register_operand" "d") |
08c2951c SC |
2548 | (match_operand:SI 2 "nonmemory_operand" "di"))) |
2549 | (clobber (match_scratch:SI 3 "=h")) | |
2550 | (clobber (match_scratch:SI 4 "=a"))] | |
7e07e3ba | 2551 | "!optimize" |
08c2951c | 2552 | "div\\t$0,%1,%2" |
8ef30996 | 2553 | [(set_attr "type" "idiv") |
0ff83799 | 2554 | (set_attr "mode" "SI")]) |
8ef30996 | 2555 | |
7e07e3ba | 2556 | (define_expand "divdi3" |
08c2951c | 2557 | [(set (match_operand:DI 0 "register_operand" "=l") |
1908a152 | 2558 | (div:DI (match_operand:DI 1 "se_register_operand" "d") |
08c2951c SC |
2559 | (match_operand:DI 2 "se_register_operand" "d"))) |
2560 | (clobber (match_scratch:DI 3 "=h")) | |
2561 | (clobber (match_scratch:DI 4 "=a"))] | |
bb621ad7 | 2562 | "TARGET_64BIT && !optimize" |
7e07e3ba GK |
2563 | " |
2564 | { | |
08c2951c SC |
2565 | emit_insn (gen_divdi3_internal (operands[0], operands[1], operands[2])); |
2566 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2567 | { | |
2568 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2569 | GEN_INT (0), |
08c2951c SC |
2570 | GEN_INT (0x7))); |
2571 | } | |
2572 | if (TARGET_CHECK_RANGE_DIV) | |
2573 | { | |
2574 | emit_insn (gen_div_trap (operands[2], | |
2575 | copy_to_mode_reg (DImode, GEN_INT (-1)), | |
2576 | GEN_INT (0x6))); | |
2577 | emit_insn (gen_div_trap (operands[2], | |
3a6ee9f4 | 2578 | copy_to_mode_reg (DImode, GEN_INT (BITMASK_HIGH)), |
08c2951c SC |
2579 | GEN_INT (0x6))); |
2580 | } | |
2581 | ||
2582 | DONE; | |
7e07e3ba GK |
2583 | }") |
2584 | ||
2585 | (define_insn "divdi3_internal" | |
08c2951c | 2586 | [(set (match_operand:DI 0 "register_operand" "=l") |
7e07e3ba | 2587 | (div:DI (match_operand:DI 1 "se_register_operand" "d") |
08c2951c SC |
2588 | (match_operand:DI 2 "se_nonmemory_operand" "di"))) |
2589 | (clobber (match_scratch:SI 3 "=h")) | |
2590 | (clobber (match_scratch:SI 4 "=a"))] | |
7e07e3ba | 2591 | "TARGET_64BIT && !optimize" |
08c2951c | 2592 | "ddiv\\t$0,%1,%2" |
bb621ad7 | 2593 | [(set_attr "type" "idiv") |
0ff83799 | 2594 | (set_attr "mode" "DI")]) |
bb621ad7 | 2595 | |
7e07e3ba | 2596 | (define_expand "modsi3" |
08c2951c | 2597 | [(set (match_operand:SI 0 "register_operand" "=h") |
8ef30996 | 2598 | (mod:SI (match_operand:SI 1 "register_operand" "d") |
08c2951c | 2599 | (match_operand:SI 2 "register_operand" "d"))) |
46299de9 | 2600 | (clobber (match_scratch:SI 3 "=l")) |
08c2951c | 2601 | (clobber (match_scratch:SI 4 "=a"))] |
34b650b3 | 2602 | "!optimize" |
7e07e3ba GK |
2603 | " |
2604 | { | |
08c2951c SC |
2605 | emit_insn (gen_modsi3_internal (operands[0], operands[1], operands[2])); |
2606 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2607 | { | |
2608 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2609 | GEN_INT (0), |
08c2951c SC |
2610 | GEN_INT (0x7))); |
2611 | } | |
2612 | if (TARGET_CHECK_RANGE_DIV) | |
2613 | { | |
2614 | emit_insn (gen_div_trap (operands[2], | |
2615 | copy_to_mode_reg (SImode, GEN_INT (-1)), | |
2616 | GEN_INT (0x6))); | |
2617 | emit_insn (gen_div_trap (operands[2], | |
3a6ee9f4 | 2618 | copy_to_mode_reg (SImode, GEN_INT (BITMASK_HIGH)), |
08c2951c SC |
2619 | GEN_INT (0x6))); |
2620 | } | |
2621 | ||
2622 | DONE; | |
7e07e3ba GK |
2623 | }") |
2624 | ||
2625 | (define_insn "modsi3_internal" | |
08c2951c | 2626 | [(set (match_operand:SI 0 "register_operand" "=h") |
7e07e3ba | 2627 | (mod:SI (match_operand:SI 1 "register_operand" "d") |
08c2951c SC |
2628 | (match_operand:SI 2 "nonmemory_operand" "di"))) |
2629 | (clobber (match_scratch:SI 3 "=l")) | |
2630 | (clobber (match_scratch:SI 4 "=a"))] | |
7e07e3ba | 2631 | "!optimize" |
08c2951c | 2632 | "div\\t$0,%1,%2" |
8ef30996 | 2633 | [(set_attr "type" "idiv") |
0ff83799 | 2634 | (set_attr "mode" "SI")]) |
bb621ad7 | 2635 | |
7e07e3ba | 2636 | (define_expand "moddi3" |
08c2951c | 2637 | [(set (match_operand:DI 0 "register_operand" "=h") |
1908a152 | 2638 | (mod:DI (match_operand:DI 1 "se_register_operand" "d") |
08c2951c | 2639 | (match_operand:DI 2 "se_register_operand" "d"))) |
46299de9 | 2640 | (clobber (match_scratch:DI 3 "=l")) |
08c2951c | 2641 | (clobber (match_scratch:DI 4 "=a"))] |
bb621ad7 | 2642 | "TARGET_64BIT && !optimize" |
7e07e3ba GK |
2643 | " |
2644 | { | |
08c2951c SC |
2645 | emit_insn (gen_moddi3_internal (operands[0], operands[1], operands[2])); |
2646 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2647 | { | |
2648 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2649 | GEN_INT (0), |
08c2951c SC |
2650 | GEN_INT (0x7))); |
2651 | } | |
2652 | if (TARGET_CHECK_RANGE_DIV) | |
2653 | { | |
2654 | emit_insn (gen_div_trap (operands[2], | |
2655 | copy_to_mode_reg (DImode, GEN_INT (-1)), | |
2656 | GEN_INT (0x6))); | |
2657 | emit_insn (gen_div_trap (operands[2], | |
3a6ee9f4 | 2658 | copy_to_mode_reg (DImode, GEN_INT (BITMASK_HIGH)), |
08c2951c SC |
2659 | GEN_INT (0x6))); |
2660 | } | |
2661 | ||
2662 | DONE; | |
7e07e3ba GK |
2663 | }") |
2664 | ||
2665 | (define_insn "moddi3_internal" | |
08c2951c | 2666 | [(set (match_operand:DI 0 "register_operand" "=h") |
7e07e3ba | 2667 | (mod:DI (match_operand:DI 1 "se_register_operand" "d") |
08c2951c SC |
2668 | (match_operand:DI 2 "se_nonmemory_operand" "di"))) |
2669 | (clobber (match_scratch:SI 3 "=l")) | |
2670 | (clobber (match_scratch:SI 4 "=a"))] | |
7e07e3ba | 2671 | "TARGET_64BIT && !optimize" |
08c2951c | 2672 | "ddiv\\t$0,%1,%2" |
bb621ad7 | 2673 | [(set_attr "type" "idiv") |
0ff83799 | 2674 | (set_attr "mode" "DI")]) |
8ef30996 | 2675 | |
7e07e3ba | 2676 | (define_expand "udivsi3" |
08c2951c | 2677 | [(set (match_operand:SI 0 "register_operand" "=l") |
8ef30996 | 2678 | (udiv:SI (match_operand:SI 1 "register_operand" "d") |
08c2951c SC |
2679 | (match_operand:SI 2 "register_operand" "d"))) |
2680 | (clobber (match_scratch:SI 3 "=h")) | |
2681 | (clobber (match_scratch:SI 4 "=a"))] | |
34b650b3 | 2682 | "!optimize" |
7e07e3ba GK |
2683 | " |
2684 | { | |
08c2951c SC |
2685 | emit_insn (gen_udivsi3_internal (operands[0], operands[1], operands[2])); |
2686 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2687 | { | |
2688 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2689 | GEN_INT (0), |
08c2951c SC |
2690 | GEN_INT (0x7))); |
2691 | } | |
2692 | ||
2693 | DONE; | |
7e07e3ba GK |
2694 | }") |
2695 | ||
2696 | (define_insn "udivsi3_internal" | |
08c2951c | 2697 | [(set (match_operand:SI 0 "register_operand" "=l") |
7e07e3ba | 2698 | (udiv:SI (match_operand:SI 1 "register_operand" "d") |
08c2951c SC |
2699 | (match_operand:SI 2 "nonmemory_operand" "di"))) |
2700 | (clobber (match_scratch:SI 3 "=h")) | |
2701 | (clobber (match_scratch:SI 4 "=a"))] | |
7e07e3ba | 2702 | "!optimize" |
08c2951c | 2703 | "divu\\t$0,%1,%2" |
8ef30996 | 2704 | [(set_attr "type" "idiv") |
0ff83799 | 2705 | (set_attr "mode" "SI")]) |
bb621ad7 | 2706 | |
7e07e3ba | 2707 | (define_expand "udivdi3" |
08c2951c | 2708 | [(set (match_operand:DI 0 "register_operand" "=l") |
1908a152 | 2709 | (udiv:DI (match_operand:DI 1 "se_register_operand" "d") |
08c2951c SC |
2710 | (match_operand:DI 2 "se_register_operand" "di"))) |
2711 | (clobber (match_scratch:DI 3 "=h")) | |
2712 | (clobber (match_scratch:DI 4 "=a"))] | |
bb621ad7 | 2713 | "TARGET_64BIT && !optimize" |
7e07e3ba GK |
2714 | " |
2715 | { | |
08c2951c SC |
2716 | emit_insn (gen_udivdi3_internal (operands[0], operands[1], operands[2])); |
2717 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2718 | { | |
2719 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2720 | GEN_INT (0), |
08c2951c SC |
2721 | GEN_INT (0x7))); |
2722 | } | |
2723 | ||
2724 | DONE; | |
7e07e3ba GK |
2725 | }") |
2726 | ||
2727 | (define_insn "udivdi3_internal" | |
08c2951c | 2728 | [(set (match_operand:DI 0 "register_operand" "=l") |
7e07e3ba | 2729 | (udiv:DI (match_operand:DI 1 "se_register_operand" "d") |
08c2951c SC |
2730 | (match_operand:DI 2 "se_nonmemory_operand" "di"))) |
2731 | (clobber (match_scratch:SI 3 "=h")) | |
2732 | (clobber (match_scratch:SI 4 "=a"))] | |
7e07e3ba | 2733 | "TARGET_64BIT && !optimize" |
08c2951c | 2734 | "ddivu\\t$0,%1,%2" |
bb621ad7 | 2735 | [(set_attr "type" "idiv") |
0ff83799 | 2736 | (set_attr "mode" "DI")]) |
8ef30996 | 2737 | |
7e07e3ba | 2738 | (define_expand "umodsi3" |
08c2951c | 2739 | [(set (match_operand:SI 0 "register_operand" "=h") |
8ef30996 | 2740 | (umod:SI (match_operand:SI 1 "register_operand" "d") |
08c2951c | 2741 | (match_operand:SI 2 "register_operand" "d"))) |
46299de9 | 2742 | (clobber (match_scratch:SI 3 "=l")) |
08c2951c | 2743 | (clobber (match_scratch:SI 4 "=a"))] |
34b650b3 | 2744 | "!optimize" |
7e07e3ba GK |
2745 | " |
2746 | { | |
08c2951c SC |
2747 | emit_insn (gen_umodsi3_internal (operands[0], operands[1], operands[2])); |
2748 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2749 | { | |
2750 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2751 | GEN_INT (0), |
08c2951c SC |
2752 | GEN_INT (0x7))); |
2753 | } | |
2754 | ||
2755 | DONE; | |
7e07e3ba GK |
2756 | }") |
2757 | ||
2758 | (define_insn "umodsi3_internal" | |
08c2951c | 2759 | [(set (match_operand:SI 0 "register_operand" "=h") |
7e07e3ba | 2760 | (umod:SI (match_operand:SI 1 "register_operand" "d") |
08c2951c SC |
2761 | (match_operand:SI 2 "nonmemory_operand" "di"))) |
2762 | (clobber (match_scratch:SI 3 "=l")) | |
2763 | (clobber (match_scratch:SI 4 "=a"))] | |
7e07e3ba | 2764 | "!optimize" |
08c2951c | 2765 | "divu\\t$0,%1,%2" |
8ef30996 | 2766 | [(set_attr "type" "idiv") |
0ff83799 | 2767 | (set_attr "mode" "SI")]) |
bb621ad7 | 2768 | |
7e07e3ba | 2769 | (define_expand "umoddi3" |
08c2951c | 2770 | [(set (match_operand:DI 0 "register_operand" "=h") |
1908a152 | 2771 | (umod:DI (match_operand:DI 1 "se_register_operand" "d") |
08c2951c | 2772 | (match_operand:DI 2 "se_register_operand" "di"))) |
46299de9 | 2773 | (clobber (match_scratch:DI 3 "=l")) |
08c2951c | 2774 | (clobber (match_scratch:DI 4 "=a"))] |
bb621ad7 | 2775 | "TARGET_64BIT && !optimize" |
7e07e3ba GK |
2776 | " |
2777 | { | |
08c2951c SC |
2778 | emit_insn (gen_umoddi3_internal (operands[0], operands[1], operands[2])); |
2779 | if (!TARGET_NO_CHECK_ZERO_DIV) | |
2780 | { | |
2781 | emit_insn (gen_div_trap (operands[2], | |
1feed51c | 2782 | GEN_INT (0), |
08c2951c SC |
2783 | GEN_INT (0x7))); |
2784 | } | |
2785 | ||
2786 | DONE; | |
7e07e3ba GK |
2787 | }") |
2788 | ||
2789 | (define_insn "umoddi3_internal" | |
08c2951c | 2790 | [(set (match_operand:DI 0 "register_operand" "=h") |
7e07e3ba | 2791 | (umod:DI (match_operand:DI 1 "se_register_operand" "d") |
08c2951c SC |
2792 | (match_operand:DI 2 "se_nonmemory_operand" "di"))) |
2793 | (clobber (match_scratch:SI 3 "=l")) | |
2794 | (clobber (match_scratch:SI 4 "=a"))] | |
7e07e3ba | 2795 | "TARGET_64BIT && !optimize" |
08c2951c | 2796 | "ddivu\\t$0,%1,%2" |
bb621ad7 | 2797 | [(set_attr "type" "idiv") |
0ff83799 | 2798 | (set_attr "mode" "DI")]) |
8ef30996 MM |
2799 | \f |
2800 | ;; | |
2801 | ;; .................... | |
2802 | ;; | |
2803 | ;; SQUARE ROOT | |
2804 | ;; | |
2805 | ;; .................... | |
2806 | ||
2807 | (define_insn "sqrtdf2" | |
2808 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2809 | (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] | |
46299de9 | 2810 | "TARGET_HARD_FLOAT && HAVE_SQRT_P() && TARGET_DOUBLE_FLOAT" |
8ef30996 | 2811 | "sqrt.d\\t%0,%1" |
bb621ad7 | 2812 | [(set_attr "type" "fsqrt") |
0ff83799 | 2813 | (set_attr "mode" "DF")]) |
8ef30996 MM |
2814 | |
2815 | (define_insn "sqrtsf2" | |
2816 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2817 | (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] | |
2818 | "TARGET_HARD_FLOAT && HAVE_SQRT_P()" | |
2819 | "sqrt.s\\t%0,%1" | |
bb621ad7 | 2820 | [(set_attr "type" "fsqrt") |
0ff83799 | 2821 | (set_attr "mode" "SF")]) |
8ef30996 | 2822 | |
b8eb88d0 ILT |
2823 | (define_insn "" |
2824 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2825 | (div:DF (match_operand:DF 1 "const_float_1_operand" "") | |
2826 | (sqrt:DF (match_operand:DF 2 "register_operand" "f"))))] | |
de6c5979 | 2827 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations" |
b8eb88d0 ILT |
2828 | "rsqrt.d\\t%0,%2" |
2829 | [(set_attr "type" "fsqrt") | |
0ff83799 | 2830 | (set_attr "mode" "DF")]) |
b8eb88d0 ILT |
2831 | |
2832 | (define_insn "" | |
2833 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2834 | (div:SF (match_operand:SF 1 "const_float_1_operand" "") | |
2835 | (sqrt:SF (match_operand:SF 2 "register_operand" "f"))))] | |
de6c5979 | 2836 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations" |
b8eb88d0 ILT |
2837 | "rsqrt.s\\t%0,%2" |
2838 | [(set_attr "type" "fsqrt") | |
0ff83799 | 2839 | (set_attr "mode" "SF")]) |
b8eb88d0 | 2840 | |
8ef30996 MM |
2841 | \f |
2842 | ;; | |
2843 | ;; .................... | |
2844 | ;; | |
2845 | ;; ABSOLUTE VALUE | |
2846 | ;; | |
2847 | ;; .................... | |
2848 | ||
2849 | ;; Do not use the integer abs macro instruction, since that signals an | |
2850 | ;; exception on -2147483648 (sigh). | |
2851 | ||
2852 | (define_insn "abssi2" | |
2853 | [(set (match_operand:SI 0 "register_operand" "=d") | |
2854 | (abs:SI (match_operand:SI 1 "register_operand" "d")))] | |
2bcb2ab3 | 2855 | "!TARGET_MIPS16" |
8ef30996 MM |
2856 | "* |
2857 | { | |
2858 | dslots_jump_total++; | |
2859 | dslots_jump_filled++; | |
2860 | operands[2] = const0_rtx; | |
2861 | ||
bb621ad7 JW |
2862 | if (REGNO (operands[0]) == REGNO (operands[1])) |
2863 | { | |
e9a25f70 | 2864 | if (GENERATE_BRANCHLIKELY) |
efa3896a | 2865 | return \"%(bltzl\\t%1,1f\\n\\tsubu\\t%0,%z2,%0\\n%~1:%)\"; |
bb621ad7 | 2866 | else |
efa3896a | 2867 | return \"bgez\\t%1,1f%#\\n\\tsubu\\t%0,%z2,%0\\n%~1:\"; |
bb621ad7 JW |
2868 | } |
2869 | else | |
efa3896a | 2870 | return \"%(bgez\\t%1,1f\\n\\tmove\\t%0,%1\\n\\tsubu\\t%0,%z2,%0\\n%~1:%)\"; |
8ef30996 MM |
2871 | }" |
2872 | [(set_attr "type" "multi") | |
2873 | (set_attr "mode" "SI") | |
0ff83799 | 2874 | (set_attr "length" "12")]) |
8ef30996 | 2875 | |
bb621ad7 JW |
2876 | (define_insn "absdi2" |
2877 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 2878 | (abs:DI (match_operand:DI 1 "se_register_operand" "d")))] |
2bcb2ab3 | 2879 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
2880 | "* |
2881 | { | |
404e4854 | 2882 | unsigned int regno1; |
bb621ad7 JW |
2883 | dslots_jump_total++; |
2884 | dslots_jump_filled++; | |
2885 | operands[2] = const0_rtx; | |
12a345cd CP |
2886 | |
2887 | if (GET_CODE (operands[1]) == REG) | |
2888 | regno1 = REGNO (operands[1]); | |
2889 | else | |
2890 | regno1 = REGNO (XEXP (operands[1], 0)); | |
bb621ad7 | 2891 | |
12a345cd | 2892 | if (REGNO (operands[0]) == regno1) |
efa3896a | 2893 | return \"%(bltzl\\t%1,1f\\n\\tdsubu\\t%0,%z2,%0\\n%~1:%)\"; |
bb621ad7 | 2894 | else |
efa3896a | 2895 | return \"%(bgez\\t%1,1f\\n\\tmove\\t%0,%1\\n\\tdsubu\\t%0,%z2,%0\\n%~1:%)\"; |
bb621ad7 JW |
2896 | }" |
2897 | [(set_attr "type" "multi") | |
2898 | (set_attr "mode" "DI") | |
0ff83799 | 2899 | (set_attr "length" "12")]) |
bb621ad7 | 2900 | |
8ef30996 MM |
2901 | (define_insn "absdf2" |
2902 | [(set (match_operand:DF 0 "register_operand" "=f") | |
2903 | (abs:DF (match_operand:DF 1 "register_operand" "f")))] | |
46299de9 | 2904 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
2905 | "abs.d\\t%0,%1" |
2906 | [(set_attr "type" "fabs") | |
0ff83799 | 2907 | (set_attr "mode" "DF")]) |
8ef30996 MM |
2908 | |
2909 | (define_insn "abssf2" | |
2910 | [(set (match_operand:SF 0 "register_operand" "=f") | |
2911 | (abs:SF (match_operand:SF 1 "register_operand" "f")))] | |
2912 | "TARGET_HARD_FLOAT" | |
2913 | "abs.s\\t%0,%1" | |
2914 | [(set_attr "type" "fabs") | |
0ff83799 | 2915 | (set_attr "mode" "SF")]) |
8ef30996 MM |
2916 | |
2917 | \f | |
2918 | ;; | |
2919 | ;; .................... | |
2920 | ;; | |
2921 | ;; FIND FIRST BIT INSTRUCTION | |
2922 | ;; | |
2923 | ;; .................... | |
2924 | ;; | |
2925 | ||
2926 | (define_insn "ffssi2" | |
2927 | [(set (match_operand:SI 0 "register_operand" "=&d") | |
2928 | (ffs:SI (match_operand:SI 1 "register_operand" "d"))) | |
7d87c851 MM |
2929 | (clobber (match_scratch:SI 2 "=&d")) |
2930 | (clobber (match_scratch:SI 3 "=&d"))] | |
2bcb2ab3 | 2931 | "!TARGET_MIPS16" |
8ef30996 MM |
2932 | "* |
2933 | { | |
2934 | dslots_jump_total += 2; | |
2935 | dslots_jump_filled += 2; | |
2936 | operands[4] = const0_rtx; | |
2937 | ||
2938 | if (optimize && find_reg_note (insn, REG_DEAD, operands[1])) | |
2939 | return \"%(\\ | |
2940 | move\\t%0,%z4\\n\\ | |
2941 | \\tbeq\\t%1,%z4,2f\\n\\ | |
efa3896a | 2942 | %~1:\\tand\\t%2,%1,0x0001\\n\\ |
8ef30996 MM |
2943 | \\taddu\\t%0,%0,1\\n\\ |
2944 | \\tbeq\\t%2,%z4,1b\\n\\ | |
2945 | \\tsrl\\t%1,%1,1\\n\\ | |
efa3896a | 2946 | %~2:%)\"; |
8ef30996 MM |
2947 | |
2948 | return \"%(\\ | |
2949 | move\\t%0,%z4\\n\\ | |
2950 | \\tmove\\t%3,%1\\n\\ | |
2951 | \\tbeq\\t%3,%z4,2f\\n\\ | |
efa3896a | 2952 | %~1:\\tand\\t%2,%3,0x0001\\n\\ |
8ef30996 MM |
2953 | \\taddu\\t%0,%0,1\\n\\ |
2954 | \\tbeq\\t%2,%z4,1b\\n\\ | |
2955 | \\tsrl\\t%3,%3,1\\n\\ | |
efa3896a | 2956 | %~2:%)\"; |
8ef30996 MM |
2957 | }" |
2958 | [(set_attr "type" "multi") | |
2959 | (set_attr "mode" "SI") | |
0ff83799 | 2960 | (set_attr "length" "12")]) |
8ef30996 | 2961 | |
bb621ad7 JW |
2962 | (define_insn "ffsdi2" |
2963 | [(set (match_operand:DI 0 "register_operand" "=&d") | |
1908a152 | 2964 | (ffs:DI (match_operand:DI 1 "se_register_operand" "d"))) |
bb621ad7 JW |
2965 | (clobber (match_scratch:DI 2 "=&d")) |
2966 | (clobber (match_scratch:DI 3 "=&d"))] | |
2bcb2ab3 | 2967 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
2968 | "* |
2969 | { | |
2970 | dslots_jump_total += 2; | |
2971 | dslots_jump_filled += 2; | |
2972 | operands[4] = const0_rtx; | |
2973 | ||
2974 | if (optimize && find_reg_note (insn, REG_DEAD, operands[1])) | |
2975 | return \"%(\\ | |
2976 | move\\t%0,%z4\\n\\ | |
2977 | \\tbeq\\t%1,%z4,2f\\n\\ | |
efa3896a | 2978 | %~1:\\tand\\t%2,%1,0x0001\\n\\ |
bb621ad7 JW |
2979 | \\tdaddu\\t%0,%0,1\\n\\ |
2980 | \\tbeq\\t%2,%z4,1b\\n\\ | |
2981 | \\tdsrl\\t%1,%1,1\\n\\ | |
efa3896a | 2982 | %~2:%)\"; |
bb621ad7 JW |
2983 | |
2984 | return \"%(\\ | |
2985 | move\\t%0,%z4\\n\\ | |
2986 | \\tmove\\t%3,%1\\n\\ | |
2987 | \\tbeq\\t%3,%z4,2f\\n\\ | |
efa3896a | 2988 | %~1:\\tand\\t%2,%3,0x0001\\n\\ |
bb621ad7 JW |
2989 | \\tdaddu\\t%0,%0,1\\n\\ |
2990 | \\tbeq\\t%2,%z4,1b\\n\\ | |
2991 | \\tdsrl\\t%3,%3,1\\n\\ | |
efa3896a | 2992 | %~2:%)\"; |
bb621ad7 JW |
2993 | }" |
2994 | [(set_attr "type" "multi") | |
2995 | (set_attr "mode" "DI") | |
0ff83799 | 2996 | (set_attr "length" "24")]) |
bb621ad7 | 2997 | |
8ef30996 MM |
2998 | \f |
2999 | ;; | |
3000 | ;; .................... | |
3001 | ;; | |
3002 | ;; NEGATION and ONE'S COMPLEMENT | |
3003 | ;; | |
3004 | ;; .................... | |
3005 | ||
3006 | (define_insn "negsi2" | |
3007 | [(set (match_operand:SI 0 "register_operand" "=d") | |
3008 | (neg:SI (match_operand:SI 1 "register_operand" "d")))] | |
3009 | "" | |
3010 | "* | |
3011 | { | |
2bcb2ab3 GK |
3012 | if (TARGET_MIPS16) |
3013 | return \"neg\\t%0,%1\"; | |
8ef30996 MM |
3014 | operands[2] = const0_rtx; |
3015 | return \"subu\\t%0,%z2,%1\"; | |
3016 | }" | |
3017 | [(set_attr "type" "arith") | |
0ff83799 | 3018 | (set_attr "mode" "SI")]) |
8ef30996 | 3019 | |
e7d7b3dc | 3020 | (define_expand "negdi2" |
8ef30996 | 3021 | [(parallel [(set (match_operand:DI 0 "register_operand" "=d") |
1908a152 | 3022 | (neg:DI (match_operand:DI 1 "se_register_operand" "d"))) |
8ef30996 | 3023 | (clobber (match_dup 2))])] |
2bcb2ab3 | 3024 | "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && !TARGET_MIPS16" |
bb621ad7 JW |
3025 | " |
3026 | { | |
3027 | if (TARGET_64BIT) | |
3028 | { | |
3029 | emit_insn (gen_negdi2_internal_2 (operands[0], operands[1])); | |
3030 | DONE; | |
3031 | } | |
3032 | ||
3033 | operands[2] = gen_reg_rtx (SImode); | |
3034 | }") | |
8ef30996 | 3035 | |
e7d7b3dc | 3036 | (define_insn "negdi2_internal" |
8ef30996 MM |
3037 | [(set (match_operand:DI 0 "register_operand" "=d") |
3038 | (neg:DI (match_operand:DI 1 "register_operand" "d"))) | |
3039 | (clobber (match_operand:SI 2 "register_operand" "=d"))] | |
2bcb2ab3 | 3040 | "! TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" |
8ef30996 MM |
3041 | "* |
3042 | { | |
3043 | operands[3] = const0_rtx; | |
3044 | return \"subu\\t%L0,%z3,%L1\;subu\\t%M0,%z3,%M1\;sltu\\t%2,%z3,%L0\;subu\\t%M0,%M0,%2\"; | |
3045 | }" | |
3046 | [(set_attr "type" "darith") | |
3047 | (set_attr "mode" "DI") | |
0ff83799 | 3048 | (set_attr "length" "16")]) |
8ef30996 | 3049 | |
bb621ad7 JW |
3050 | (define_insn "negdi2_internal_2" |
3051 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 3052 | (neg:DI (match_operand:DI 1 "se_register_operand" "d")))] |
2bcb2ab3 | 3053 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
3054 | "* |
3055 | { | |
3056 | operands[2] = const0_rtx; | |
3057 | return \"dsubu\\t%0,%z2,%1\"; | |
3058 | }" | |
3059 | [(set_attr "type" "arith") | |
0ff83799 | 3060 | (set_attr "mode" "DI")]) |
bb621ad7 | 3061 | |
8ef30996 MM |
3062 | (define_insn "negdf2" |
3063 | [(set (match_operand:DF 0 "register_operand" "=f") | |
3064 | (neg:DF (match_operand:DF 1 "register_operand" "f")))] | |
46299de9 | 3065 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
3066 | "neg.d\\t%0,%1" |
3067 | [(set_attr "type" "fneg") | |
0ff83799 | 3068 | (set_attr "mode" "DF")]) |
8ef30996 MM |
3069 | |
3070 | (define_insn "negsf2" | |
3071 | [(set (match_operand:SF 0 "register_operand" "=f") | |
3072 | (neg:SF (match_operand:SF 1 "register_operand" "f")))] | |
3073 | "TARGET_HARD_FLOAT" | |
3074 | "neg.s\\t%0,%1" | |
3075 | [(set_attr "type" "fneg") | |
0ff83799 | 3076 | (set_attr "mode" "SF")]) |
8ef30996 MM |
3077 | |
3078 | (define_insn "one_cmplsi2" | |
3079 | [(set (match_operand:SI 0 "register_operand" "=d") | |
3080 | (not:SI (match_operand:SI 1 "register_operand" "d")))] | |
3081 | "" | |
3082 | "* | |
3083 | { | |
2bcb2ab3 GK |
3084 | if (TARGET_MIPS16) |
3085 | return \"not\\t%0,%1\"; | |
8ef30996 MM |
3086 | operands[2] = const0_rtx; |
3087 | return \"nor\\t%0,%z2,%1\"; | |
3088 | }" | |
3089 | [(set_attr "type" "arith") | |
0ff83799 | 3090 | (set_attr "mode" "SI")]) |
8ef30996 MM |
3091 | |
3092 | (define_insn "one_cmpldi2" | |
3093 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 3094 | (not:DI (match_operand:DI 1 "se_register_operand" "d")))] |
8ef30996 MM |
3095 | "" |
3096 | "* | |
3097 | { | |
2bcb2ab3 GK |
3098 | if (TARGET_MIPS16) |
3099 | { | |
3100 | if (TARGET_64BIT) | |
3101 | return \"not\\t%0,%1\"; | |
3102 | return \"not\\t%M0,%M1\;not\\t%L0,%L1\"; | |
3103 | } | |
8ef30996 | 3104 | operands[2] = const0_rtx; |
bb621ad7 JW |
3105 | if (TARGET_64BIT) |
3106 | return \"nor\\t%0,%z2,%1\"; | |
8ef30996 MM |
3107 | return \"nor\\t%M0,%z2,%M1\;nor\\t%L0,%z2,%L1\"; |
3108 | }" | |
3109 | [(set_attr "type" "darith") | |
3110 | (set_attr "mode" "DI") | |
bb621ad7 JW |
3111 | (set (attr "length") |
3112 | (if_then_else (ge (symbol_ref "mips_isa") (const_int 3)) | |
0ff83799 MM |
3113 | (const_int 4) |
3114 | (const_int 8)))]) | |
8ef30996 MM |
3115 | |
3116 | (define_split | |
3117 | [(set (match_operand:DI 0 "register_operand" "") | |
3118 | (not:DI (match_operand:DI 1 "register_operand" "")))] | |
bb621ad7 | 3119 | "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
8ef30996 MM |
3120 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
3121 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" | |
3122 | ||
3123 | [(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0))) | |
ddef6bc7 | 3124 | (set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))] |
8ef30996 MM |
3125 | "") |
3126 | ||
8ef30996 MM |
3127 | \f |
3128 | ;; | |
3129 | ;; .................... | |
3130 | ;; | |
3131 | ;; LOGICAL | |
3132 | ;; | |
3133 | ;; .................... | |
3134 | ;; | |
3135 | ||
2bcb2ab3 GK |
3136 | ;; Many of these instructions uses trivial define_expands, because we |
3137 | ;; want to use a different set of constraints when TARGET_MIPS16. | |
3138 | ||
3139 | (define_expand "andsi3" | |
65437fe8 | 3140 | [(set (match_operand:SI 0 "register_operand" "=d,d") |
e2f2127c MM |
3141 | (and:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") |
3142 | (match_operand:SI 2 "uns_arith_operand" "d,K")))] | |
65437fe8 | 3143 | "" |
2bcb2ab3 GK |
3144 | " |
3145 | { | |
3146 | if (TARGET_MIPS16) | |
3147 | operands[2] = force_reg (SImode, operands[2]); | |
3148 | }") | |
3149 | ||
3150 | (define_insn "" | |
3151 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
3152 | (and:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") | |
3153 | (match_operand:SI 2 "uns_arith_operand" "d,K")))] | |
3154 | "!TARGET_MIPS16" | |
65437fe8 MM |
3155 | "@ |
3156 | and\\t%0,%1,%2 | |
3157 | andi\\t%0,%1,%x2" | |
3158 | [(set_attr "type" "arith") | |
0ff83799 | 3159 | (set_attr "mode" "SI")]) |
65437fe8 | 3160 | |
2bcb2ab3 GK |
3161 | (define_insn "" |
3162 | [(set (match_operand:SI 0 "register_operand" "=d") | |
3163 | (and:SI (match_operand:SI 1 "register_operand" "%0") | |
3164 | (match_operand:SI 2 "register_operand" "d")))] | |
3165 | "TARGET_MIPS16" | |
3166 | "and\\t%0,%2" | |
3167 | [(set_attr "type" "arith") | |
0ff83799 | 3168 | (set_attr "mode" "SI")]) |
2bcb2ab3 GK |
3169 | |
3170 | (define_expand "anddi3" | |
8ef30996 | 3171 | [(set (match_operand:DI 0 "register_operand" "=d") |
1908a152 ILT |
3172 | (and:DI (match_operand:DI 1 "se_register_operand" "d") |
3173 | (match_operand:DI 2 "se_register_operand" "d")))] | |
bb621ad7 | 3174 | "TARGET_64BIT || !TARGET_DEBUG_G_MODE" |
2bcb2ab3 GK |
3175 | " |
3176 | { | |
3177 | if (TARGET_MIPS16) | |
3178 | operands[2] = force_reg (DImode, operands[2]); | |
3179 | }") | |
3180 | ||
3181 | (define_insn "" | |
3182 | [(set (match_operand:DI 0 "register_operand" "=d") | |
3183 | (and:DI (match_operand:DI 1 "se_register_operand" "d") | |
3184 | (match_operand:DI 2 "se_register_operand" "d")))] | |
3185 | "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && !TARGET_MIPS16" | |
bb621ad7 JW |
3186 | "* |
3187 | { | |
3188 | if (TARGET_64BIT) | |
3189 | return \"and\\t%0,%1,%2\"; | |
3190 | return \"and\\t%M0,%M1,%M2\;and\\t%L0,%L1,%L2\"; | |
3191 | }" | |
8ef30996 MM |
3192 | [(set_attr "type" "darith") |
3193 | (set_attr "mode" "DI") | |
bb621ad7 | 3194 | (set (attr "length") |
77a8368e | 3195 | (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0)) |
0ff83799 MM |
3196 | (const_int 4) |
3197 | (const_int 8)))]) | |
8ef30996 | 3198 | |
2bcb2ab3 GK |
3199 | (define_insn "" |
3200 | [(set (match_operand:DI 0 "register_operand" "=d") | |
3201 | (and:DI (match_operand:DI 1 "se_register_operand" "0") | |
3202 | (match_operand:DI 2 "se_register_operand" "d")))] | |
3203 | "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && TARGET_MIPS16" | |
3204 | "* | |
3205 | { | |
3206 | if (TARGET_64BIT) | |
3207 | return \"and\\t%0,%2\"; | |
3208 | return \"and\\t%M0,%M2\;and\\t%L0,%L2\"; | |
3209 | }" | |
3210 | [(set_attr "type" "darith") | |
3211 | (set_attr "mode" "DI") | |
3212 | (set (attr "length") | |
3213 | (if_then_else (ge (symbol_ref "mips_isa") (const_int 3)) | |
0ff83799 MM |
3214 | (const_int 4) |
3215 | (const_int 8)))]) | |
2bcb2ab3 | 3216 | |
8ef30996 MM |
3217 | (define_split |
3218 | [(set (match_operand:DI 0 "register_operand" "") | |
3219 | (and:DI (match_operand:DI 1 "register_operand" "") | |
3220 | (match_operand:DI 2 "register_operand" "")))] | |
bb621ad7 | 3221 | "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
8ef30996 MM |
3222 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
3223 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
3224 | && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" | |
3225 | ||
3226 | [(set (subreg:SI (match_dup 0) 0) (and:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) | |
ddef6bc7 | 3227 | (set (subreg:SI (match_dup 0) 4) (and:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))] |
8ef30996 MM |
3228 | "") |
3229 | ||
bb621ad7 JW |
3230 | (define_insn "anddi3_internal1" |
3231 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
1908a152 ILT |
3232 | (and:DI (match_operand:DI 1 "se_register_operand" "%d,d") |
3233 | (match_operand:DI 2 "se_uns_arith_operand" "d,K")))] | |
2bcb2ab3 | 3234 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
3235 | "@ |
3236 | and\\t%0,%1,%2 | |
3237 | andi\\t%0,%1,%x2" | |
3238 | [(set_attr "type" "arith") | |
0ff83799 | 3239 | (set_attr "mode" "DI")]) |
bb621ad7 | 3240 | |
2bcb2ab3 | 3241 | (define_expand "iorsi3" |
65437fe8 | 3242 | [(set (match_operand:SI 0 "register_operand" "=d,d") |
e2f2127c MM |
3243 | (ior:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") |
3244 | (match_operand:SI 2 "uns_arith_operand" "d,K")))] | |
65437fe8 | 3245 | "" |
2bcb2ab3 GK |
3246 | " |
3247 | { | |
3248 | if (TARGET_MIPS16) | |
3249 | operands[2] = force_reg (SImode, operands[2]); | |
3250 | }") | |
3251 | ||
3252 | (define_insn "" | |
3253 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
3254 | (ior:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") | |
3255 | (match_operand:SI 2 "uns_arith_operand" "d,K")))] | |
3256 | "!TARGET_MIPS16" | |
65437fe8 MM |
3257 | "@ |
3258 | or\\t%0,%1,%2 | |
3259 | ori\\t%0,%1,%x2" | |
3260 | [(set_attr "type" "arith") | |
0ff83799 | 3261 | (set_attr "mode" "SI")]) |
65437fe8 | 3262 | |
2bcb2ab3 GK |
3263 | (define_insn "" |
3264 | [(set (match_operand:SI 0 "register_operand" "=d") | |
3265 | (ior:SI (match_operand:SI 1 "register_operand" "%0") | |
3266 | (match_operand:SI 2 "register_operand" "d")))] | |
3267 | "TARGET_MIPS16" | |
3268 | "or\\t%0,%2" | |
3269 | [(set_attr "type" "arith") | |
0ff83799 | 3270 | (set_attr "mode" "SI")]) |
2bcb2ab3 | 3271 | |
bb621ad7 JW |
3272 | ;;; ??? There is no iordi3 pattern which accepts 'K' constants when |
3273 | ;;; TARGET_64BIT | |
3274 | ||
2bcb2ab3 | 3275 | (define_expand "iordi3" |
8ef30996 | 3276 | [(set (match_operand:DI 0 "register_operand" "=d") |
1908a152 ILT |
3277 | (ior:DI (match_operand:DI 1 "se_register_operand" "d") |
3278 | (match_operand:DI 2 "se_register_operand" "d")))] | |
bb621ad7 | 3279 | "TARGET_64BIT || !TARGET_DEBUG_G_MODE" |
2bcb2ab3 GK |
3280 | "") |
3281 | ||
3282 | (define_insn "" | |
3283 | [(set (match_operand:DI 0 "register_operand" "=d") | |
3284 | (ior:DI (match_operand:DI 1 "se_register_operand" "d") | |
3285 | (match_operand:DI 2 "se_register_operand" "d")))] | |
3286 | "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && !TARGET_MIPS16" | |
bb621ad7 JW |
3287 | "* |
3288 | { | |
3289 | if (TARGET_64BIT) | |
3290 | return \"or\\t%0,%1,%2\"; | |
3291 | return \"or\\t%M0,%M1,%M2\;or\\t%L0,%L1,%L2\"; | |
3292 | }" | |
8ef30996 MM |
3293 | [(set_attr "type" "darith") |
3294 | (set_attr "mode" "DI") | |
bb621ad7 | 3295 | (set (attr "length") |
77a8368e | 3296 | (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0)) |
0ff83799 MM |
3297 | (const_int 4) |
3298 | (const_int 8)))]) | |
8ef30996 | 3299 | |
2bcb2ab3 GK |
3300 | (define_insn "" |
3301 | [(set (match_operand:DI 0 "register_operand" "=d") | |
3302 | (ior:DI (match_operand:DI 1 "se_register_operand" "0") | |
3303 | (match_operand:DI 2 "se_register_operand" "d")))] | |
3304 | "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && TARGET_MIPS16" | |
3305 | "* | |
3306 | { | |
3307 | if (TARGET_64BIT) | |
3308 | return \"or\\t%0,%2\"; | |
3309 | return \"or\\t%M0,%M2\;or\\t%L0,%L2\"; | |
3310 | }" | |
3311 | [(set_attr "type" "darith") | |
3312 | (set_attr "mode" "DI") | |
3313 | (set (attr "length") | |
3314 | (if_then_else (ge (symbol_ref "mips_isa") (const_int 3)) | |
0ff83799 MM |
3315 | (const_int 4) |
3316 | (const_int 8)))]) | |
2bcb2ab3 | 3317 | |
8ef30996 MM |
3318 | (define_split |
3319 | [(set (match_operand:DI 0 "register_operand" "") | |
3320 | (ior:DI (match_operand:DI 1 "register_operand" "") | |
3321 | (match_operand:DI 2 "register_operand" "")))] | |
bb621ad7 | 3322 | "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
8ef30996 MM |
3323 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
3324 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
3325 | && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" | |
3326 | ||
3327 | [(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) | |
ddef6bc7 | 3328 | (set (subreg:SI (match_dup 0) 4) (ior:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))] |
8ef30996 MM |
3329 | "") |
3330 | ||
2bcb2ab3 | 3331 | (define_expand "xorsi3" |
65437fe8 | 3332 | [(set (match_operand:SI 0 "register_operand" "=d,d") |
e2f2127c MM |
3333 | (xor:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") |
3334 | (match_operand:SI 2 "uns_arith_operand" "d,K")))] | |
65437fe8 | 3335 | "" |
2bcb2ab3 GK |
3336 | "") |
3337 | ||
3338 | (define_insn "" | |
3339 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
3340 | (xor:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") | |
3341 | (match_operand:SI 2 "uns_arith_operand" "d,K")))] | |
3342 | "!TARGET_MIPS16" | |
65437fe8 MM |
3343 | "@ |
3344 | xor\\t%0,%1,%2 | |
3345 | xori\\t%0,%1,%x2" | |
3346 | [(set_attr "type" "arith") | |
0ff83799 | 3347 | (set_attr "mode" "SI")]) |
65437fe8 | 3348 | |
2bcb2ab3 GK |
3349 | (define_insn "" |
3350 | [(set (match_operand:SI 0 "register_operand" "=d,t,t") | |
3351 | (xor:SI (match_operand:SI 1 "uns_arith_operand" "%0,d,d") | |
3352 | (match_operand:SI 2 "uns_arith_operand" "d,K,d")))] | |
3353 | "TARGET_MIPS16" | |
3354 | "@ | |
3355 | xor\\t%0,%2 | |
3356 | cmpi\\t%1,%2 | |
3357 | cmp\\t%1,%2" | |
3358 | [(set_attr "type" "arith") | |
3359 | (set_attr "mode" "SI") | |
3360 | (set_attr_alternative "length" | |
0ff83799 | 3361 | [(const_int 4) |
2bcb2ab3 | 3362 | (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") |
0ff83799 MM |
3363 | (const_int 4) |
3364 | (const_int 8)) | |
3365 | (const_int 4)])]) | |
2bcb2ab3 | 3366 | |
bb621ad7 JW |
3367 | ;; ??? If delete the 32-bit long long patterns, then could merge this with |
3368 | ;; the following xordi3_internal pattern. | |
2bcb2ab3 | 3369 | (define_expand "xordi3" |
8ef30996 | 3370 | [(set (match_operand:DI 0 "register_operand" "=d") |
1908a152 ILT |
3371 | (xor:DI (match_operand:DI 1 "se_register_operand" "d") |
3372 | (match_operand:DI 2 "se_register_operand" "d")))] | |
bb621ad7 | 3373 | "TARGET_64BIT || !TARGET_DEBUG_G_MODE" |
2bcb2ab3 GK |
3374 | "") |
3375 | ||
3376 | (define_insn "" | |
3377 | [(set (match_operand:DI 0 "register_operand" "=d") | |
3378 | (xor:DI (match_operand:DI 1 "se_register_operand" "d") | |
3379 | (match_operand:DI 2 "se_register_operand" "d")))] | |
3380 | "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && !TARGET_MIPS16" | |
bb621ad7 JW |
3381 | "* |
3382 | { | |
3383 | if (TARGET_64BIT) | |
3384 | return \"xor\\t%0,%1,%2\"; | |
3385 | return \"xor\\t%M0,%M1,%M2\;xor\\t%L0,%L1,%L2\"; | |
3386 | }" | |
3387 | [(set_attr "type" "darith") | |
8ef30996 | 3388 | (set_attr "mode" "DI") |
bb621ad7 | 3389 | (set (attr "length") |
77a8368e | 3390 | (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0)) |
0ff83799 MM |
3391 | (const_int 4) |
3392 | (const_int 8)))]) | |
8ef30996 | 3393 | |
2bcb2ab3 GK |
3394 | (define_insn "" |
3395 | [(set (match_operand:DI 0 "register_operand" "=d") | |
3396 | (xor:DI (match_operand:DI 1 "se_register_operand" "0") | |
3397 | (match_operand:DI 2 "se_register_operand" "d")))] | |
3398 | "!TARGET_64BIT && TARGET_MIPS16" | |
3399 | "xor\\t%M0,%M2\;xor\\t%L0,%L2" | |
3400 | [(set_attr "type" "darith") | |
3401 | (set_attr "mode" "DI") | |
0ff83799 | 3402 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
3403 | |
3404 | (define_insn "" | |
3405 | [(set (match_operand:DI 0 "register_operand" "=d,t,t") | |
3406 | (xor:DI (match_operand:DI 1 "se_register_operand" "%0,d,d") | |
3407 | (match_operand:DI 2 "se_uns_arith_operand" "d,K,d")))] | |
3408 | "TARGET_64BIT && TARGET_MIPS16" | |
3409 | "@ | |
3410 | xor\\t%0,%2 | |
3411 | cmpi\\t%1,%2 | |
3412 | cmp\\t%1,%2" | |
3413 | [(set_attr "type" "arith") | |
3414 | (set_attr "mode" "DI") | |
3415 | (set_attr_alternative "length" | |
0ff83799 | 3416 | [(const_int 4) |
2bcb2ab3 | 3417 | (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") |
0ff83799 MM |
3418 | (const_int 4) |
3419 | (const_int 8)) | |
3420 | (const_int 4)])]) | |
2bcb2ab3 | 3421 | |
8ef30996 MM |
3422 | (define_split |
3423 | [(set (match_operand:DI 0 "register_operand" "") | |
3424 | (xor:DI (match_operand:DI 1 "register_operand" "") | |
3425 | (match_operand:DI 2 "register_operand" "")))] | |
bb621ad7 | 3426 | "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
8ef30996 MM |
3427 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
3428 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
3429 | && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" | |
3430 | ||
3431 | [(set (subreg:SI (match_dup 0) 0) (xor:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) | |
ddef6bc7 | 3432 | (set (subreg:SI (match_dup 0) 4) (xor:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))] |
8ef30996 MM |
3433 | "") |
3434 | ||
bb621ad7 | 3435 | (define_insn "xordi3_immed" |
2bcb2ab3 | 3436 | [(set (match_operand:DI 0 "register_operand" "=d") |
1908a152 ILT |
3437 | (xor:DI (match_operand:DI 1 "se_register_operand" "d") |
3438 | (match_operand:DI 2 "se_uns_arith_operand" "K")))] | |
2bcb2ab3 | 3439 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
3440 | "xori\\t%0,%1,%x2" |
3441 | [(set_attr "type" "arith") | |
0ff83799 | 3442 | (set_attr "mode" "DI")]) |
bb621ad7 | 3443 | |
77a8368e JW |
3444 | (define_insn "*norsi3" |
3445 | [(set (match_operand:SI 0 "register_operand" "=d") | |
3446 | (and:SI (not:SI (match_operand:SI 1 "register_operand" "d")) | |
3447 | (not:SI (match_operand:SI 2 "register_operand" "d"))))] | |
2bcb2ab3 | 3448 | "!TARGET_MIPS16" |
77a8368e JW |
3449 | "nor\\t%0,%z1,%z2" |
3450 | [(set_attr "type" "arith") | |
0ff83799 | 3451 | (set_attr "mode" "SI")]) |
77a8368e JW |
3452 | |
3453 | (define_insn "*nordi3" | |
3454 | [(set (match_operand:DI 0 "register_operand" "=d") | |
3455 | (and:DI (not:DI (match_operand:DI 1 "se_register_operand" "d")) | |
3456 | (not:DI (match_operand:DI 2 "se_register_operand" "d"))))] | |
2bcb2ab3 | 3457 | "!TARGET_MIPS16" |
77a8368e JW |
3458 | "* |
3459 | { | |
3460 | if (TARGET_64BIT) | |
3461 | return \"nor\\t%0,%z1,%z2\"; | |
3462 | return \"nor\\t%M0,%M1,%M2\;nor\\t%L0,%L1,%L2\"; | |
3463 | }" | |
3464 | [(set_attr "type" "darith") | |
3465 | (set_attr "mode" "DI") | |
3466 | (set (attr "length") | |
3467 | (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0)) | |
0ff83799 MM |
3468 | (const_int 4) |
3469 | (const_int 8)))]) | |
77a8368e JW |
3470 | |
3471 | (define_split | |
3472 | [(set (match_operand:DI 0 "register_operand" "") | |
3473 | (and:DI (not:DI (match_operand:DI 1 "register_operand" "")) | |
3474 | (not:DI (match_operand:DI 2 "register_operand" ""))))] | |
2bcb2ab3 | 3475 | "reload_completed && !TARGET_MIPS16 && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
77a8368e JW |
3476 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
3477 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) | |
3478 | && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" | |
3479 | ||
3480 | [(set (subreg:SI (match_dup 0) 0) (and:SI (not:SI (subreg:SI (match_dup 1) 0)) (not:SI (subreg:SI (match_dup 2) 0)))) | |
ddef6bc7 | 3481 | (set (subreg:SI (match_dup 0) 4) (and:SI (not:SI (subreg:SI (match_dup 1) 4)) (not:SI (subreg:SI (match_dup 2) 4))))] |
77a8368e | 3482 | "") |
8ef30996 MM |
3483 | \f |
3484 | ;; | |
3485 | ;; .................... | |
3486 | ;; | |
3487 | ;; TRUNCATION | |
3488 | ;; | |
3489 | ;; .................... | |
3490 | ||
3491 | (define_insn "truncdfsf2" | |
3492 | [(set (match_operand:SF 0 "register_operand" "=f") | |
3493 | (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] | |
46299de9 | 3494 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
3495 | "cvt.s.d\\t%0,%1" |
3496 | [(set_attr "type" "fcvt") | |
0ff83799 | 3497 | (set_attr "mode" "SF")]) |
8ef30996 | 3498 | |
8894cf34 JW |
3499 | (define_insn "truncdisi2" |
3500 | [(set (match_operand:SI 0 "register_operand" "=d") | |
1908a152 | 3501 | (truncate:SI (match_operand:DI 1 "se_register_operand" "d")))] |
bb621ad7 | 3502 | "TARGET_64BIT" |
2bcb2ab3 GK |
3503 | "* |
3504 | { | |
3505 | if (TARGET_MIPS16) | |
3506 | return \"dsll\\t%0,%1,32\;dsra\\t%0,32\"; | |
3507 | return \"dsll\\t%0,%1,32\;dsra\\t%0,%0,32\"; | |
3508 | }" | |
8894cf34 JW |
3509 | [(set_attr "type" "darith") |
3510 | (set_attr "mode" "SI") | |
2bcb2ab3 | 3511 | (set (attr "length") (if_then_else (eq (symbol_ref "mips16") (const_int 0)) |
0ff83799 MM |
3512 | (const_int 8) |
3513 | (const_int 16)))]) | |
bb621ad7 | 3514 | |
8894cf34 JW |
3515 | (define_insn "truncdihi2" |
3516 | [(set (match_operand:HI 0 "register_operand" "=d") | |
1908a152 | 3517 | (truncate:HI (match_operand:DI 1 "se_register_operand" "d")))] |
00bb4b62 GK |
3518 | "TARGET_64BIT" |
3519 | "* | |
3520 | { | |
3521 | if (TARGET_MIPS16) | |
3522 | return \"dsll\\t%0,%1,48\;dsra\\t%0,48\"; | |
3523 | return \"andi\\t%0,%1,0xffff\"; | |
3524 | }" | |
8894cf34 JW |
3525 | [(set_attr "type" "darith") |
3526 | (set_attr "mode" "HI") | |
00bb4b62 | 3527 | (set (attr "length") (if_then_else (eq (symbol_ref "mips16") (const_int 0)) |
0ff83799 MM |
3528 | (const_int 4) |
3529 | (const_int 16)))]) | |
8894cf34 JW |
3530 | (define_insn "truncdiqi2" |
3531 | [(set (match_operand:QI 0 "register_operand" "=d") | |
1908a152 | 3532 | (truncate:QI (match_operand:DI 1 "se_register_operand" "d")))] |
00bb4b62 GK |
3533 | "TARGET_64BIT" |
3534 | "* | |
3535 | { | |
3536 | if (TARGET_MIPS16) | |
3537 | return \"dsll\\t%0,%1,56\;dsra\\t%0,56\"; | |
3538 | return \"andi\\t%0,%1,0x00ff\"; | |
3539 | }" | |
8894cf34 JW |
3540 | [(set_attr "type" "darith") |
3541 | (set_attr "mode" "QI") | |
00bb4b62 | 3542 | (set (attr "length") (if_then_else (eq (symbol_ref "mips16") (const_int 0)) |
0ff83799 MM |
3543 | (const_int 4) |
3544 | (const_int 16)))]) | |
a67f7692 JW |
3545 | |
3546 | ;; Combiner patterns to optimize shift/truncate combinations. | |
3547 | (define_insn "" | |
3548 | [(set (match_operand:SI 0 "register_operand" "=d") | |
1908a152 | 3549 | (truncate:SI (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "d") |
a67f7692 | 3550 | (match_operand:DI 2 "small_int" "I"))))] |
2bcb2ab3 | 3551 | "TARGET_64BIT && !TARGET_MIPS16" |
a67f7692 JW |
3552 | "* |
3553 | { | |
3554 | int shift_amt = INTVAL (operands[2]) & 0x3f; | |
3555 | ||
3556 | if (shift_amt < 32) | |
3557 | { | |
3558 | operands[2] = GEN_INT (32 - shift_amt); | |
3559 | return \"dsll\\t%0,%1,%2\;dsra\\t%0,%0,32\"; | |
3560 | } | |
3561 | else | |
3562 | { | |
3563 | operands[2] = GEN_INT (shift_amt); | |
3564 | return \"dsra\\t%0,%1,%2\"; | |
3565 | } | |
3566 | }" | |
3567 | [(set_attr "type" "darith") | |
3568 | (set_attr "mode" "SI") | |
0ff83799 | 3569 | (set_attr "length" "8")]) |
a67f7692 JW |
3570 | |
3571 | (define_insn "" | |
3572 | [(set (match_operand:SI 0 "register_operand" "=d") | |
1908a152 | 3573 | (truncate:SI (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "d") |
a67f7692 | 3574 | (match_operand:DI 2 "small_int" "I"))))] |
2bcb2ab3 | 3575 | "TARGET_64BIT && !TARGET_MIPS16" |
a67f7692 JW |
3576 | "* |
3577 | { | |
3578 | int shift_amt = INTVAL (operands[2]) & 0x3f; | |
3579 | ||
3580 | if (shift_amt < 32) | |
3581 | { | |
3582 | operands[2] = GEN_INT (32 - shift_amt); | |
3583 | return \"dsll\\t%0,%1,%2\;dsra\\t%0,%0,32\"; | |
3584 | } | |
3585 | else if (shift_amt == 32) | |
3586 | return \"dsra\\t%0,%1,32\"; | |
3587 | else | |
3588 | { | |
3589 | operands[2] = GEN_INT (shift_amt); | |
3590 | return \"dsrl\\t%0,%1,%2\"; | |
3591 | } | |
3592 | }" | |
3593 | [(set_attr "type" "darith") | |
3594 | (set_attr "mode" "SI") | |
0ff83799 | 3595 | (set_attr "length" "8")]) |
a67f7692 JW |
3596 | |
3597 | (define_insn "" | |
3598 | [(set (match_operand:SI 0 "register_operand" "=d") | |
1908a152 | 3599 | (truncate:SI (ashift:DI (match_operand:DI 1 "se_register_operand" "d") |
a67f7692 JW |
3600 | (match_operand:DI 2 "small_int" "I"))))] |
3601 | "TARGET_64BIT" | |
3602 | "* | |
3603 | { | |
3604 | int shift_amt = INTVAL (operands[2]) & 0x3f; | |
3605 | ||
3606 | if (shift_amt < 32) | |
3607 | { | |
3608 | operands[2] = GEN_INT (32 + shift_amt); | |
2bcb2ab3 GK |
3609 | if (TARGET_MIPS16) |
3610 | return \"dsll\\t%0,%1,%2\;dsra\\t%0,32\"; | |
a67f7692 JW |
3611 | return \"dsll\\t%0,%1,%2\;dsra\\t%0,%0,32\"; |
3612 | } | |
3613 | else | |
3614 | return \"move\\t%0,%.\"; | |
3615 | }" | |
3616 | [(set_attr "type" "darith") | |
3617 | (set_attr "mode" "SI") | |
0ff83799 | 3618 | (set_attr "length" "8")]) |
99f762bf JW |
3619 | |
3620 | ;; Combiner patterns to optimize truncate/zero_extend combinations. | |
3621 | ||
3622 | (define_insn "" | |
3623 | [(set (match_operand:SI 0 "register_operand" "=d") | |
3624 | (zero_extend:SI (truncate:HI | |
1908a152 | 3625 | (match_operand:DI 1 "se_register_operand" "d"))))] |
2bcb2ab3 | 3626 | "TARGET_64BIT && !TARGET_MIPS16" |
99f762bf JW |
3627 | "andi\\t%0,%1,0xffff" |
3628 | [(set_attr "type" "darith") | |
0ff83799 | 3629 | (set_attr "mode" "SI")]) |
99f762bf JW |
3630 | |
3631 | (define_insn "" | |
3632 | [(set (match_operand:SI 0 "register_operand" "=d") | |
3633 | (zero_extend:SI (truncate:QI | |
1908a152 | 3634 | (match_operand:DI 1 "se_register_operand" "d"))))] |
2bcb2ab3 | 3635 | "TARGET_64BIT && !TARGET_MIPS16" |
99f762bf JW |
3636 | "andi\\t%0,%1,0xff" |
3637 | [(set_attr "type" "darith") | |
0ff83799 | 3638 | (set_attr "mode" "SI")]) |
99f762bf JW |
3639 | |
3640 | (define_insn "" | |
3641 | [(set (match_operand:HI 0 "register_operand" "=d") | |
3642 | (zero_extend:HI (truncate:QI | |
1908a152 | 3643 | (match_operand:DI 1 "se_register_operand" "d"))))] |
2bcb2ab3 | 3644 | "TARGET_64BIT && !TARGET_MIPS16" |
99f762bf JW |
3645 | "andi\\t%0,%1,0xff" |
3646 | [(set_attr "type" "darith") | |
0ff83799 | 3647 | (set_attr "mode" "HI")]) |
8ef30996 MM |
3648 | \f |
3649 | ;; | |
3650 | ;; .................... | |
3651 | ;; | |
3652 | ;; ZERO EXTENSION | |
3653 | ;; | |
3654 | ;; .................... | |
3655 | ||
3656 | ;; Extension insns. | |
abdf3eea | 3657 | ;; Those for integer source operand are ordered widest source type first. |
8ef30996 | 3658 | |
bb621ad7 JW |
3659 | (define_expand "zero_extendsidi2" |
3660 | [(set (match_operand:DI 0 "register_operand" "") | |
3661 | (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))] | |
3662 | "TARGET_64BIT" | |
3663 | " | |
3664 | { | |
32fdad6e | 3665 | if ((optimize || TARGET_MIPS16) && GET_CODE (operands[1]) == MEM) |
bb621ad7 JW |
3666 | operands[1] = force_not_mem (operands[1]); |
3667 | ||
3668 | if (GET_CODE (operands[1]) != MEM) | |
3669 | { | |
3670 | rtx op1 = gen_lowpart (DImode, operands[1]); | |
3671 | rtx temp = gen_reg_rtx (DImode); | |
95936d18 | 3672 | rtx shift = GEN_INT (32); |
bb621ad7 JW |
3673 | |
3674 | emit_insn (gen_ashldi3 (temp, op1, shift)); | |
3675 | emit_insn (gen_lshrdi3 (operands[0], temp, shift)); | |
3676 | DONE; | |
3677 | } | |
3678 | }") | |
3679 | ||
3680 | (define_insn "zero_extendsidi2_internal" | |
3681 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
3682 | (zero_extend:DI (match_operand:SI 1 "memory_operand" "R,m")))] | |
b5031ab7 | 3683 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
3684 | "* return mips_move_1word (operands, insn, TRUE);" |
3685 | [(set_attr "type" "load") | |
3686 | (set_attr "mode" "DI") | |
0ff83799 | 3687 | (set_attr "length" "4,8")]) |
bb621ad7 | 3688 | |
2bcb2ab3 GK |
3689 | (define_expand "zero_extendhisi2" |
3690 | [(set (match_operand:SI 0 "register_operand" "") | |
3691 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] | |
3692 | "" | |
3693 | " | |
3694 | { | |
3695 | if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) | |
3696 | { | |
3697 | rtx op = gen_lowpart (SImode, operands[1]); | |
3698 | rtx temp = force_reg (SImode, GEN_INT (0xffff)); | |
3699 | ||
3700 | emit_insn (gen_andsi3 (operands[0], op, temp)); | |
3701 | DONE; | |
3702 | } | |
3703 | }") | |
3704 | ||
3705 | (define_insn "" | |
8ef30996 MM |
3706 | [(set (match_operand:SI 0 "register_operand" "=d,d,d") |
3707 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))] | |
2bcb2ab3 | 3708 | "!TARGET_MIPS16" |
8ef30996 MM |
3709 | "* |
3710 | { | |
3711 | if (which_alternative == 0) | |
3712 | return \"andi\\t%0,%1,0xffff\"; | |
3713 | else | |
3714 | return mips_move_1word (operands, insn, TRUE); | |
3715 | }" | |
3716 | [(set_attr "type" "arith,load,load") | |
92b4cee1 | 3717 | (set_attr "mode" "SI") |
0ff83799 | 3718 | (set_attr "length" "4,4,8")]) |
8ef30996 | 3719 | |
2bcb2ab3 GK |
3720 | (define_insn "" |
3721 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
3722 | (zero_extend:SI (match_operand:HI 1 "memory_operand" "R,m")))] | |
3723 | "TARGET_MIPS16" | |
3724 | "* return mips_move_1word (operands, insn, TRUE);" | |
3725 | [(set_attr "type" "load,load") | |
3726 | (set_attr "mode" "SI") | |
0ff83799 | 3727 | (set_attr "length" "4,8")]) |
2bcb2ab3 GK |
3728 | |
3729 | (define_expand "zero_extendhidi2" | |
3730 | [(set (match_operand:DI 0 "register_operand" "") | |
3731 | (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "")))] | |
3732 | "TARGET_64BIT" | |
3733 | " | |
3734 | { | |
3735 | if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) | |
3736 | { | |
3737 | rtx op = gen_lowpart (DImode, operands[1]); | |
3738 | rtx temp = force_reg (DImode, GEN_INT (0xffff)); | |
3739 | ||
3740 | emit_insn (gen_anddi3 (operands[0], op, temp)); | |
3741 | DONE; | |
3742 | } | |
3743 | }") | |
3744 | ||
3745 | (define_insn "" | |
bb621ad7 JW |
3746 | [(set (match_operand:DI 0 "register_operand" "=d,d,d") |
3747 | (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))] | |
2bcb2ab3 | 3748 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
3749 | "* |
3750 | { | |
3751 | if (which_alternative == 0) | |
3752 | return \"andi\\t%0,%1,0xffff\"; | |
3753 | else | |
3754 | return mips_move_1word (operands, insn, TRUE); | |
3755 | }" | |
3756 | [(set_attr "type" "arith,load,load") | |
3757 | (set_attr "mode" "DI") | |
0ff83799 | 3758 | (set_attr "length" "4,4,8")]) |
bb621ad7 | 3759 | |
2bcb2ab3 GK |
3760 | (define_insn "" |
3761 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
3762 | (zero_extend:DI (match_operand:HI 1 "memory_operand" "R,m")))] | |
3763 | "TARGET_64BIT && TARGET_MIPS16" | |
3764 | "* return mips_move_1word (operands, insn, TRUE);" | |
3765 | [(set_attr "type" "load,load") | |
3766 | (set_attr "mode" "DI") | |
0ff83799 | 3767 | (set_attr "length" "4,8")]) |
2bcb2ab3 GK |
3768 | |
3769 | (define_expand "zero_extendqihi2" | |
3770 | [(set (match_operand:HI 0 "register_operand" "") | |
3771 | (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] | |
3772 | "" | |
3773 | " | |
3774 | { | |
3775 | if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) | |
3776 | { | |
3777 | rtx op0 = gen_lowpart (SImode, operands[0]); | |
3778 | rtx op1 = gen_lowpart (SImode, operands[1]); | |
3779 | rtx temp = force_reg (SImode, GEN_INT (0xff)); | |
3780 | ||
3781 | emit_insn (gen_andsi3 (op0, op1, temp)); | |
3782 | DONE; | |
3783 | } | |
3784 | }") | |
3785 | ||
3786 | (define_insn "" | |
8ef30996 MM |
3787 | [(set (match_operand:HI 0 "register_operand" "=d,d,d") |
3788 | (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] | |
2bcb2ab3 | 3789 | "!TARGET_MIPS16" |
8ef30996 MM |
3790 | "* |
3791 | { | |
3792 | if (which_alternative == 0) | |
3793 | return \"andi\\t%0,%1,0x00ff\"; | |
3794 | else | |
3795 | return mips_move_1word (operands, insn, TRUE); | |
3796 | }" | |
3797 | [(set_attr "type" "arith,load,load") | |
92b4cee1 | 3798 | (set_attr "mode" "HI") |
0ff83799 | 3799 | (set_attr "length" "4,4,8")]) |
8ef30996 | 3800 | |
2bcb2ab3 GK |
3801 | (define_insn "" |
3802 | [(set (match_operand:HI 0 "register_operand" "=d,d") | |
3803 | (zero_extend:HI (match_operand:QI 1 "memory_operand" "R,m")))] | |
3804 | "TARGET_MIPS16" | |
3805 | "* return mips_move_1word (operands, insn, TRUE);" | |
3806 | [(set_attr "type" "load,load") | |
3807 | (set_attr "mode" "HI") | |
0ff83799 | 3808 | (set_attr "length" "4,8")]) |
2bcb2ab3 GK |
3809 | |
3810 | (define_expand "zero_extendqisi2" | |
3811 | [(set (match_operand:SI 0 "register_operand" "") | |
3812 | (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] | |
3813 | "" | |
3814 | " | |
3815 | { | |
3816 | if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) | |
3817 | { | |
3818 | rtx op = gen_lowpart (SImode, operands[1]); | |
3819 | rtx temp = force_reg (SImode, GEN_INT (0xff)); | |
3820 | ||
3821 | emit_insn (gen_andsi3 (operands[0], op, temp)); | |
3822 | DONE; | |
3823 | } | |
3824 | }") | |
3825 | ||
3826 | (define_insn "" | |
8ef30996 MM |
3827 | [(set (match_operand:SI 0 "register_operand" "=d,d,d") |
3828 | (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] | |
2bcb2ab3 | 3829 | "!TARGET_MIPS16" |
8ef30996 MM |
3830 | "* |
3831 | { | |
3832 | if (which_alternative == 0) | |
3833 | return \"andi\\t%0,%1,0x00ff\"; | |
3834 | else | |
3835 | return mips_move_1word (operands, insn, TRUE); | |
3836 | }" | |
3837 | [(set_attr "type" "arith,load,load") | |
92b4cee1 | 3838 | (set_attr "mode" "SI") |
0ff83799 | 3839 | (set_attr "length" "4,4,8")]) |
8ef30996 | 3840 | |
2bcb2ab3 GK |
3841 | (define_insn "" |
3842 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
3843 | (zero_extend:SI (match_operand:QI 1 "memory_operand" "R,m")))] | |
3844 | "TARGET_MIPS16" | |
3845 | "* return mips_move_1word (operands, insn, TRUE);" | |
3846 | [(set_attr "type" "load,load") | |
3847 | (set_attr "mode" "SI") | |
0ff83799 | 3848 | (set_attr "length" "4,8")]) |
2bcb2ab3 GK |
3849 | |
3850 | (define_expand "zero_extendqidi2" | |
3851 | [(set (match_operand:DI 0 "register_operand" "") | |
3852 | (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))] | |
3853 | "TARGET_64BIT" | |
3854 | " | |
3855 | { | |
3856 | if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) | |
3857 | { | |
3858 | rtx op = gen_lowpart (DImode, operands[1]); | |
3859 | rtx temp = force_reg (DImode, GEN_INT (0xff)); | |
3860 | ||
3861 | emit_insn (gen_anddi3 (operands[0], op, temp)); | |
3862 | DONE; | |
3863 | } | |
3864 | }") | |
3865 | ||
3866 | (define_insn "" | |
bb621ad7 JW |
3867 | [(set (match_operand:DI 0 "register_operand" "=d,d,d") |
3868 | (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] | |
2bcb2ab3 | 3869 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
3870 | "* |
3871 | { | |
3872 | if (which_alternative == 0) | |
3873 | return \"andi\\t%0,%1,0x00ff\"; | |
3874 | else | |
3875 | return mips_move_1word (operands, insn, TRUE); | |
3876 | }" | |
3877 | [(set_attr "type" "arith,load,load") | |
3878 | (set_attr "mode" "DI") | |
0ff83799 | 3879 | (set_attr "length" "4,4,8")]) |
bb621ad7 | 3880 | |
3cce8bc6 JW |
3881 | ;; These can be created when a paradoxical subreg operand with an implicit |
3882 | ;; sign_extend operator is reloaded. Because of the subreg, this is really | |
3883 | ;; a zero extend. | |
3884 | ;; ??? It might be possible to eliminate the need for these patterns by adding | |
3885 | ;; more support to reload for implicit sign_extend operators. | |
3886 | (define_insn "*paradoxical_extendhidi2" | |
3887 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
3888 | (sign_extend:DI | |
3889 | (subreg:SI (match_operand:HI 1 "memory_operand" "R,m") 0)))] | |
3890 | "TARGET_64BIT" | |
3891 | "* | |
3892 | { | |
3893 | return mips_move_1word (operands, insn, TRUE); | |
3894 | }" | |
3895 | [(set_attr "type" "load,load") | |
3896 | (set_attr "mode" "DI") | |
0ff83799 | 3897 | (set_attr "length" "4,8")]) |
3cce8bc6 | 3898 | |
2bcb2ab3 | 3899 | (define_insn "" |
3cce8bc6 | 3900 | [(set (match_operand:DI 0 "register_operand" "=d,d") |
2bcb2ab3 GK |
3901 | (zero_extend:DI (match_operand:QI 1 "memory_operand" "R,m")))] |
3902 | "TARGET_64BIT && TARGET_MIPS16" | |
3903 | "* return mips_move_1word (operands, insn, TRUE);" | |
3cce8bc6 JW |
3904 | [(set_attr "type" "load,load") |
3905 | (set_attr "mode" "DI") | |
0ff83799 | 3906 | (set_attr "length" "4,8")]) |
8ef30996 MM |
3907 | \f |
3908 | ;; | |
3909 | ;; .................... | |
3910 | ;; | |
3911 | ;; SIGN EXTENSION | |
3912 | ;; | |
3913 | ;; .................... | |
3914 | ||
3915 | ;; Extension insns. | |
abdf3eea | 3916 | ;; Those for integer source operand are ordered widest source type first. |
8ef30996 | 3917 | |
bbae0daa ILT |
3918 | ;; In 64 bit mode, 32 bit values in general registers are always |
3919 | ;; correctly sign extended. That means that if the target is a | |
3920 | ;; general register, we can sign extend from SImode to DImode just by | |
3921 | ;; doing a move. | |
abdf3eea | 3922 | |
bbae0daa | 3923 | (define_insn "extendsidi2" |
2e72fa6a GK |
3924 | [(set (match_operand:DI 0 "register_operand" "=d,y,d,*d,d,d") |
3925 | (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,d,y,*x,R,m")))] | |
abdf3eea JW |
3926 | "TARGET_64BIT" |
3927 | "* return mips_move_1word (operands, insn, FALSE);" | |
2e72fa6a | 3928 | [(set_attr "type" "move,move,move,hilo,load,load") |
bb621ad7 | 3929 | (set_attr "mode" "DI") |
0ff83799 | 3930 | (set_attr "length" "4,4,4,4,4,8")]) |
bb621ad7 | 3931 | |
8ef30996 MM |
3932 | ;; These patterns originally accepted general_operands, however, slightly |
3933 | ;; better code is generated by only accepting register_operands, and then | |
3934 | ;; letting combine generate the lh and lb insns. | |
3935 | ||
bb621ad7 JW |
3936 | (define_expand "extendhidi2" |
3937 | [(set (match_operand:DI 0 "register_operand" "") | |
3938 | (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "")))] | |
3939 | "TARGET_64BIT" | |
3940 | " | |
3941 | { | |
3942 | if (optimize && GET_CODE (operands[1]) == MEM) | |
3943 | operands[1] = force_not_mem (operands[1]); | |
3944 | ||
3945 | if (GET_CODE (operands[1]) != MEM) | |
3946 | { | |
3947 | rtx op1 = gen_lowpart (DImode, operands[1]); | |
3948 | rtx temp = gen_reg_rtx (DImode); | |
95936d18 | 3949 | rtx shift = GEN_INT (48); |
bb621ad7 JW |
3950 | |
3951 | emit_insn (gen_ashldi3 (temp, op1, shift)); | |
3952 | emit_insn (gen_ashrdi3 (operands[0], temp, shift)); | |
3953 | DONE; | |
3954 | } | |
3955 | }") | |
3956 | ||
3957 | (define_insn "extendhidi2_internal" | |
3958 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
3959 | (sign_extend:DI (match_operand:HI 1 "memory_operand" "R,m")))] | |
3960 | "TARGET_64BIT" | |
3961 | "* return mips_move_1word (operands, insn, FALSE);" | |
3962 | [(set_attr "type" "load") | |
3963 | (set_attr "mode" "DI") | |
0ff83799 | 3964 | (set_attr "length" "4,8")]) |
bb621ad7 | 3965 | |
8ef30996 MM |
3966 | (define_expand "extendhisi2" |
3967 | [(set (match_operand:SI 0 "register_operand" "") | |
3968 | (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] | |
3969 | "" | |
3970 | " | |
3971 | { | |
3972 | if (optimize && GET_CODE (operands[1]) == MEM) | |
3973 | operands[1] = force_not_mem (operands[1]); | |
3974 | ||
3975 | if (GET_CODE (operands[1]) != MEM) | |
3976 | { | |
3977 | rtx op1 = gen_lowpart (SImode, operands[1]); | |
3978 | rtx temp = gen_reg_rtx (SImode); | |
95936d18 | 3979 | rtx shift = GEN_INT (16); |
8ef30996 MM |
3980 | |
3981 | emit_insn (gen_ashlsi3 (temp, op1, shift)); | |
3982 | emit_insn (gen_ashrsi3 (operands[0], temp, shift)); | |
3983 | DONE; | |
3984 | } | |
3985 | }") | |
3986 | ||
3987 | (define_insn "extendhisi2_internal" | |
3988 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
3989 | (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,m")))] | |
3990 | "" | |
3991 | "* return mips_move_1word (operands, insn, FALSE);" | |
92b4cee1 MM |
3992 | [(set_attr "type" "load") |
3993 | (set_attr "mode" "SI") | |
0ff83799 | 3994 | (set_attr "length" "4,8")]) |
8ef30996 MM |
3995 | |
3996 | (define_expand "extendqihi2" | |
3997 | [(set (match_operand:HI 0 "register_operand" "") | |
3998 | (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] | |
3999 | "" | |
4000 | " | |
4001 | { | |
4002 | if (optimize && GET_CODE (operands[1]) == MEM) | |
4003 | operands[1] = force_not_mem (operands[1]); | |
4004 | ||
4005 | if (GET_CODE (operands[1]) != MEM) | |
4006 | { | |
4007 | rtx op0 = gen_lowpart (SImode, operands[0]); | |
4008 | rtx op1 = gen_lowpart (SImode, operands[1]); | |
4009 | rtx temp = gen_reg_rtx (SImode); | |
95936d18 | 4010 | rtx shift = GEN_INT (24); |
8ef30996 MM |
4011 | |
4012 | emit_insn (gen_ashlsi3 (temp, op1, shift)); | |
4013 | emit_insn (gen_ashrsi3 (op0, temp, shift)); | |
4014 | DONE; | |
4015 | } | |
4016 | }") | |
4017 | ||
4018 | (define_insn "extendqihi2_internal" | |
4019 | [(set (match_operand:HI 0 "register_operand" "=d,d") | |
4020 | (sign_extend:HI (match_operand:QI 1 "memory_operand" "R,m")))] | |
4021 | "" | |
4022 | "* return mips_move_1word (operands, insn, FALSE);" | |
92b4cee1 MM |
4023 | [(set_attr "type" "load") |
4024 | (set_attr "mode" "SI") | |
0ff83799 | 4025 | (set_attr "length" "4,8")]) |
8ef30996 MM |
4026 | |
4027 | ||
4028 | (define_expand "extendqisi2" | |
4029 | [(set (match_operand:SI 0 "register_operand" "") | |
4030 | (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] | |
4031 | "" | |
4032 | " | |
4033 | { | |
4034 | if (optimize && GET_CODE (operands[1]) == MEM) | |
4035 | operands[1] = force_not_mem (operands[1]); | |
4036 | ||
4037 | if (GET_CODE (operands[1]) != MEM) | |
4038 | { | |
4039 | rtx op1 = gen_lowpart (SImode, operands[1]); | |
4040 | rtx temp = gen_reg_rtx (SImode); | |
95936d18 | 4041 | rtx shift = GEN_INT (24); |
8ef30996 MM |
4042 | |
4043 | emit_insn (gen_ashlsi3 (temp, op1, shift)); | |
4044 | emit_insn (gen_ashrsi3 (operands[0], temp, shift)); | |
4045 | DONE; | |
4046 | } | |
4047 | }") | |
4048 | ||
4049 | (define_insn "extendqisi2_insn" | |
4050 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
4051 | (sign_extend:SI (match_operand:QI 1 "memory_operand" "R,m")))] | |
4052 | "" | |
4053 | "* return mips_move_1word (operands, insn, FALSE);" | |
92b4cee1 MM |
4054 | [(set_attr "type" "load") |
4055 | (set_attr "mode" "SI") | |
0ff83799 | 4056 | (set_attr "length" "4,8")]) |
8ef30996 | 4057 | |
bb621ad7 JW |
4058 | (define_expand "extendqidi2" |
4059 | [(set (match_operand:DI 0 "register_operand" "") | |
4060 | (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))] | |
4061 | "TARGET_64BIT" | |
4062 | " | |
4063 | { | |
4064 | if (optimize && GET_CODE (operands[1]) == MEM) | |
4065 | operands[1] = force_not_mem (operands[1]); | |
4066 | ||
4067 | if (GET_CODE (operands[1]) != MEM) | |
4068 | { | |
4069 | rtx op1 = gen_lowpart (DImode, operands[1]); | |
4070 | rtx temp = gen_reg_rtx (DImode); | |
95936d18 | 4071 | rtx shift = GEN_INT (56); |
bb621ad7 JW |
4072 | |
4073 | emit_insn (gen_ashldi3 (temp, op1, shift)); | |
4074 | emit_insn (gen_ashrdi3 (operands[0], temp, shift)); | |
4075 | DONE; | |
4076 | } | |
4077 | }") | |
4078 | ||
4079 | (define_insn "extendqidi2_insn" | |
4080 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
4081 | (sign_extend:DI (match_operand:QI 1 "memory_operand" "R,m")))] | |
4082 | "TARGET_64BIT" | |
4083 | "* return mips_move_1word (operands, insn, FALSE);" | |
4084 | [(set_attr "type" "load") | |
4085 | (set_attr "mode" "DI") | |
0ff83799 | 4086 | (set_attr "length" "4,8")]) |
bb621ad7 | 4087 | |
8ef30996 MM |
4088 | |
4089 | (define_insn "extendsfdf2" | |
4090 | [(set (match_operand:DF 0 "register_operand" "=f") | |
4091 | (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] | |
46299de9 | 4092 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
4093 | "cvt.d.s\\t%0,%1" |
4094 | [(set_attr "type" "fcvt") | |
0ff83799 | 4095 | (set_attr "mode" "DF")]) |
8ef30996 MM |
4096 | |
4097 | \f | |
4098 | ||
4099 | ;; | |
4100 | ;; .................... | |
4101 | ;; | |
4102 | ;; CONVERSIONS | |
4103 | ;; | |
4104 | ;; .................... | |
4105 | ||
d1460eef JW |
4106 | ;; The SImode scratch register can not be shared with address regs used for |
4107 | ;; operand zero, because then the address in the move instruction will be | |
4108 | ;; clobbered. We mark the scratch register as early clobbered to prevent this. | |
4109 | ||
0609f021 JW |
4110 | ;; We need the ?X in alternative 1 so that it will be choosen only if the |
4111 | ;; destination is a floating point register. Otherwise, alternative 1 can | |
4112 | ;; have lower cost than alternative 0 (because there is one less loser), and | |
4113 | ;; can be choosen when it won't work (because integral reloads into FP | |
4114 | ;; registers are not supported). | |
4115 | ||
c7343333 | 4116 | (define_insn "fix_truncdfsi2" |
0e7e9155 | 4117 | [(set (match_operand:SI 0 "nonimmediate_operand" "=d,*f,R,To") |
8ef30996 | 4118 | (fix:SI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) |
d1460eef | 4119 | (clobber (match_scratch:SI 2 "=d,*d,&d,&d")) |
0609f021 | 4120 | (clobber (match_scratch:DF 3 "=f,?*X,f,f"))] |
46299de9 | 4121 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
4122 | "* |
4123 | { | |
4124 | rtx xoperands[10]; | |
4125 | ||
4126 | if (which_alternative == 1) | |
4127 | return \"trunc.w.d %0,%1,%2\"; | |
4128 | ||
4129 | output_asm_insn (\"trunc.w.d %3,%1,%2\", operands); | |
4130 | ||
4131 | xoperands[0] = operands[0]; | |
4132 | xoperands[1] = operands[3]; | |
4133 | output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); | |
4134 | return \"\"; | |
4135 | }" | |
92b4cee1 MM |
4136 | [(set_attr "type" "fcvt") |
4137 | (set_attr "mode" "DF") | |
0ff83799 | 4138 | (set_attr "length" "44,36,40,44")]) |
8ef30996 MM |
4139 | |
4140 | ||
c7343333 | 4141 | (define_insn "fix_truncsfsi2" |
0e7e9155 | 4142 | [(set (match_operand:SI 0 "nonimmediate_operand" "=d,*f,R,To") |
8ef30996 | 4143 | (fix:SI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) |
d1460eef | 4144 | (clobber (match_scratch:SI 2 "=d,*d,&d,&d")) |
0609f021 | 4145 | (clobber (match_scratch:SF 3 "=f,?*X,f,f"))] |
8ef30996 MM |
4146 | "TARGET_HARD_FLOAT" |
4147 | "* | |
4148 | { | |
4149 | rtx xoperands[10]; | |
4150 | ||
4151 | if (which_alternative == 1) | |
4152 | return \"trunc.w.s %0,%1,%2\"; | |
4153 | ||
4154 | output_asm_insn (\"trunc.w.s %3,%1,%2\", operands); | |
4155 | ||
4156 | xoperands[0] = operands[0]; | |
4157 | xoperands[1] = operands[3]; | |
4158 | output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); | |
4159 | return \"\"; | |
4160 | }" | |
92b4cee1 MM |
4161 | [(set_attr "type" "fcvt") |
4162 | (set_attr "mode" "SF") | |
0ff83799 | 4163 | (set_attr "length" "44,36,40,44")]) |
8ef30996 MM |
4164 | |
4165 | ||
bb621ad7 JW |
4166 | ;;; ??? trunc.l.d is mentioned in the appendix of the 1993 r4000/r4600 manuals |
4167 | ;;; but not in the chapter that describes the FPU. It is not mentioned at all | |
4168 | ;;; in the 1991 manuals. The r4000 at Cygnus does not have this instruction. | |
4169 | ||
4170 | ;;; Deleting this means that we now need two libgcc2.a libraries. One for | |
4171 | ;;; the 32 bit calling convention and one for the 64 bit calling convention. | |
4172 | ||
4173 | ;;; If this is disabled, then fixuns_truncdfdi2 must be disabled also. | |
4174 | ||
4175 | (define_insn "fix_truncdfdi2" | |
0e7e9155 | 4176 | [(set (match_operand:DI 0 "nonimmediate_operand" "=d,*f,R,To") |
bb621ad7 | 4177 | (fix:DI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) |
0609f021 | 4178 | (clobber (match_scratch:DF 2 "=f,?*X,f,f"))] |
46299de9 | 4179 | "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" |
bb621ad7 JW |
4180 | "* |
4181 | { | |
4182 | rtx xoperands[10]; | |
4183 | ||
4184 | if (which_alternative == 1) | |
4185 | return \"trunc.l.d %0,%1\"; | |
4186 | ||
4187 | output_asm_insn (\"trunc.l.d %2,%1\", operands); | |
4188 | ||
4189 | xoperands[0] = operands[0]; | |
4190 | xoperands[1] = operands[2]; | |
bd9f1972 | 4191 | output_asm_insn (mips_move_2words (xoperands, insn), xoperands); |
bb621ad7 JW |
4192 | return \"\"; |
4193 | }" | |
4194 | [(set_attr "type" "fcvt") | |
4195 | (set_attr "mode" "DF") | |
0ff83799 | 4196 | (set_attr "length" "8,4,8,12")]) |
bb621ad7 JW |
4197 | |
4198 | ||
4199 | ;;; ??? trunc.l.s is mentioned in the appendix of the 1993 r4000/r4600 manuals | |
4200 | ;;; but not in the chapter that describes the FPU. It is not mentioned at all | |
4201 | ;;; in the 1991 manuals. The r4000 at Cygnus does not have this instruction. | |
4202 | (define_insn "fix_truncsfdi2" | |
0e7e9155 | 4203 | [(set (match_operand:DI 0 "nonimmediate_operand" "=d,*f,R,To") |
bb621ad7 | 4204 | (fix:DI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) |
0609f021 | 4205 | (clobber (match_scratch:DF 2 "=f,?*X,f,f"))] |
46299de9 | 4206 | "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" |
bb621ad7 JW |
4207 | "* |
4208 | { | |
4209 | rtx xoperands[10]; | |
4210 | ||
4211 | if (which_alternative == 1) | |
4212 | return \"trunc.l.s %0,%1\"; | |
4213 | ||
4214 | output_asm_insn (\"trunc.l.s %2,%1\", operands); | |
4215 | ||
4216 | xoperands[0] = operands[0]; | |
4217 | xoperands[1] = operands[2]; | |
bd9f1972 | 4218 | output_asm_insn (mips_move_2words (xoperands, insn), xoperands); |
bb621ad7 JW |
4219 | return \"\"; |
4220 | }" | |
4221 | [(set_attr "type" "fcvt") | |
4222 | (set_attr "mode" "SF") | |
0ff83799 | 4223 | (set_attr "length" "8,4,8,12")]) |
bb621ad7 JW |
4224 | |
4225 | ||
8ef30996 | 4226 | (define_insn "floatsidf2" |
bbdb5552 MM |
4227 | [(set (match_operand:DF 0 "register_operand" "=f,f,f") |
4228 | (float:DF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] | |
46299de9 | 4229 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
bbdb5552 MM |
4230 | "* |
4231 | { | |
4232 | dslots_load_total++; | |
4233 | if (GET_CODE (operands[1]) == MEM) | |
5cccf78f | 4234 | return \"l.s\\t%0,%1%#\;cvt.d.w\\t%0,%0\"; |
bbdb5552 MM |
4235 | |
4236 | return \"mtc1\\t%1,%0%#\;cvt.d.w\\t%0,%0\"; | |
4237 | }" | |
92b4cee1 MM |
4238 | [(set_attr "type" "fcvt") |
4239 | (set_attr "mode" "DF") | |
0ff83799 | 4240 | (set_attr "length" "12,16,12")]) |
8ef30996 | 4241 | |
c7343333 | 4242 | |
bb621ad7 JW |
4243 | (define_insn "floatdidf2" |
4244 | [(set (match_operand:DF 0 "register_operand" "=f,f,f") | |
1908a152 | 4245 | (float:DF (match_operand:DI 1 "se_nonimmediate_operand" "d,R,m")))] |
46299de9 | 4246 | "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" |
bb621ad7 JW |
4247 | "* |
4248 | { | |
4249 | dslots_load_total++; | |
4250 | if (GET_CODE (operands[1]) == MEM) | |
4251 | return \"l.d\\t%0,%1%#\;cvt.d.l\\t%0,%0\"; | |
4252 | ||
4253 | return \"dmtc1\\t%1,%0%#\;cvt.d.l\\t%0,%0\"; | |
4254 | }" | |
4255 | [(set_attr "type" "fcvt") | |
4256 | (set_attr "mode" "DF") | |
0ff83799 | 4257 | (set_attr "length" "12,16,12")]) |
bb621ad7 JW |
4258 | |
4259 | ||
8ef30996 | 4260 | (define_insn "floatsisf2" |
bbdb5552 MM |
4261 | [(set (match_operand:SF 0 "register_operand" "=f,f,f") |
4262 | (float:SF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] | |
8ef30996 | 4263 | "TARGET_HARD_FLOAT" |
bbdb5552 MM |
4264 | "* |
4265 | { | |
4266 | dslots_load_total++; | |
4267 | if (GET_CODE (operands[1]) == MEM) | |
5cccf78f | 4268 | return \"l.s\\t%0,%1%#\;cvt.s.w\\t%0,%0\"; |
bbdb5552 MM |
4269 | |
4270 | return \"mtc1\\t%1,%0%#\;cvt.s.w\\t%0,%0\"; | |
4271 | }" | |
92b4cee1 MM |
4272 | [(set_attr "type" "fcvt") |
4273 | (set_attr "mode" "SF") | |
0ff83799 | 4274 | (set_attr "length" "12,16,12")]) |
bbdb5552 | 4275 | |
8ef30996 | 4276 | |
bb621ad7 JW |
4277 | (define_insn "floatdisf2" |
4278 | [(set (match_operand:SF 0 "register_operand" "=f,f,f") | |
1908a152 | 4279 | (float:SF (match_operand:DI 1 "se_nonimmediate_operand" "d,R,m")))] |
46299de9 | 4280 | "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" |
bb621ad7 JW |
4281 | "* |
4282 | { | |
4283 | dslots_load_total++; | |
4284 | if (GET_CODE (operands[1]) == MEM) | |
4285 | return \"l.d\\t%0,%1%#\;cvt.s.l\\t%0,%0\"; | |
4286 | ||
4287 | return \"dmtc1\\t%1,%0%#\;cvt.s.l\\t%0,%0\"; | |
4288 | }" | |
4289 | [(set_attr "type" "fcvt") | |
4290 | (set_attr "mode" "SF") | |
0ff83799 | 4291 | (set_attr "length" "12,16,12")]) |
bb621ad7 JW |
4292 | |
4293 | ||
8ef30996 MM |
4294 | (define_expand "fixuns_truncdfsi2" |
4295 | [(set (match_operand:SI 0 "register_operand" "") | |
4296 | (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))] | |
46299de9 | 4297 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
4298 | " |
4299 | { | |
4300 | rtx reg1 = gen_reg_rtx (DFmode); | |
4301 | rtx reg2 = gen_reg_rtx (DFmode); | |
4302 | rtx reg3 = gen_reg_rtx (SImode); | |
4303 | rtx label1 = gen_label_rtx (); | |
4304 | rtx label2 = gen_label_rtx (); | |
4305 | REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31); | |
4306 | ||
4307 | if (reg1) /* turn off complaints about unreached code */ | |
4308 | { | |
8ef30996 MM |
4309 | emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); |
4310 | do_pending_stack_adjust (); | |
4311 | ||
4312 | emit_insn (gen_cmpdf (operands[1], reg1)); | |
4313 | emit_jump_insn (gen_bge (label1)); | |
4314 | ||
4315 | emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1])); | |
c5c76735 JL |
4316 | emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, |
4317 | gen_rtx_LABEL_REF (VOIDmode, label2))); | |
8ef30996 MM |
4318 | emit_barrier (); |
4319 | ||
4320 | emit_label (label1); | |
c5c76735 | 4321 | emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); |
3a6ee9f4 | 4322 | emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); |
8ef30996 MM |
4323 | |
4324 | emit_insn (gen_fix_truncdfsi2 (operands[0], reg2)); | |
4325 | emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); | |
4326 | ||
4327 | emit_label (label2); | |
4328 | ||
4329 | /* allow REG_NOTES to be set on last insn (labels don't have enough | |
4330 | fields, and can't be used for REG_NOTES anyway). */ | |
c5c76735 | 4331 | emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); |
8ef30996 MM |
4332 | DONE; |
4333 | } | |
4334 | }") | |
4335 | ||
c7343333 | 4336 | |
bb621ad7 JW |
4337 | (define_expand "fixuns_truncdfdi2" |
4338 | [(set (match_operand:DI 0 "register_operand" "") | |
4339 | (unsigned_fix:DI (match_operand:DF 1 "register_operand" "")))] | |
46299de9 | 4340 | "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" |
bb621ad7 JW |
4341 | " |
4342 | { | |
4343 | rtx reg1 = gen_reg_rtx (DFmode); | |
4344 | rtx reg2 = gen_reg_rtx (DFmode); | |
4345 | rtx reg3 = gen_reg_rtx (DImode); | |
4346 | rtx label1 = gen_label_rtx (); | |
4347 | rtx label2 = gen_label_rtx (); | |
4348 | REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 63); | |
4349 | ||
4350 | if (reg1) /* turn off complaints about unreached code */ | |
4351 | { | |
4352 | emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); | |
4353 | do_pending_stack_adjust (); | |
4354 | ||
4355 | emit_insn (gen_cmpdf (operands[1], reg1)); | |
4356 | emit_jump_insn (gen_bge (label1)); | |
4357 | ||
4358 | emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1])); | |
c5c76735 JL |
4359 | emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, |
4360 | gen_rtx_LABEL_REF (VOIDmode, label2))); | |
bb621ad7 JW |
4361 | emit_barrier (); |
4362 | ||
4363 | emit_label (label1); | |
c5c76735 | 4364 | emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); |
3a6ee9f4 | 4365 | emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); |
bb621ad7 JW |
4366 | emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); |
4367 | ||
4368 | emit_insn (gen_fix_truncdfdi2 (operands[0], reg2)); | |
4369 | emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); | |
4370 | ||
4371 | emit_label (label2); | |
4372 | ||
4373 | /* allow REG_NOTES to be set on last insn (labels don't have enough | |
4374 | fields, and can't be used for REG_NOTES anyway). */ | |
c5c76735 | 4375 | emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); |
bb621ad7 JW |
4376 | DONE; |
4377 | } | |
4378 | }") | |
4379 | ||
4380 | ||
8ef30996 MM |
4381 | (define_expand "fixuns_truncsfsi2" |
4382 | [(set (match_operand:SI 0 "register_operand" "") | |
4383 | (unsigned_fix:SI (match_operand:SF 1 "register_operand" "")))] | |
4384 | "TARGET_HARD_FLOAT" | |
4385 | " | |
4386 | { | |
4387 | rtx reg1 = gen_reg_rtx (SFmode); | |
4388 | rtx reg2 = gen_reg_rtx (SFmode); | |
4389 | rtx reg3 = gen_reg_rtx (SImode); | |
4390 | rtx label1 = gen_label_rtx (); | |
4391 | rtx label2 = gen_label_rtx (); | |
4392 | REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31); | |
4393 | ||
4394 | if (reg1) /* turn off complaints about unreached code */ | |
4395 | { | |
8ef30996 MM |
4396 | emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); |
4397 | do_pending_stack_adjust (); | |
4398 | ||
4399 | emit_insn (gen_cmpsf (operands[1], reg1)); | |
4400 | emit_jump_insn (gen_bge (label1)); | |
4401 | ||
4402 | emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1])); | |
c5c76735 JL |
4403 | emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, |
4404 | gen_rtx_LABEL_REF (VOIDmode, label2))); | |
8ef30996 MM |
4405 | emit_barrier (); |
4406 | ||
4407 | emit_label (label1); | |
c5c76735 | 4408 | emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); |
3a6ee9f4 | 4409 | emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); |
8ef30996 MM |
4410 | |
4411 | emit_insn (gen_fix_truncsfsi2 (operands[0], reg2)); | |
4412 | emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); | |
4413 | ||
4414 | emit_label (label2); | |
4415 | ||
4416 | /* allow REG_NOTES to be set on last insn (labels don't have enough | |
4417 | fields, and can't be used for REG_NOTES anyway). */ | |
c5c76735 | 4418 | emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); |
8ef30996 MM |
4419 | DONE; |
4420 | } | |
4421 | }") | |
4422 | ||
8ef30996 | 4423 | |
bb621ad7 JW |
4424 | (define_expand "fixuns_truncsfdi2" |
4425 | [(set (match_operand:DI 0 "register_operand" "") | |
4426 | (unsigned_fix:DI (match_operand:SF 1 "register_operand" "")))] | |
46299de9 | 4427 | "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
4428 | " |
4429 | { | |
bb621ad7 JW |
4430 | rtx reg1 = gen_reg_rtx (SFmode); |
4431 | rtx reg2 = gen_reg_rtx (SFmode); | |
4432 | rtx reg3 = gen_reg_rtx (DImode); | |
4433 | rtx label1 = gen_label_rtx (); | |
4434 | rtx label2 = gen_label_rtx (); | |
4435 | REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 63); | |
8ef30996 | 4436 | |
bb621ad7 | 4437 | if (reg1) /* turn off complaints about unreached code */ |
8ef30996 | 4438 | { |
bb621ad7 JW |
4439 | emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); |
4440 | do_pending_stack_adjust (); | |
8ef30996 | 4441 | |
bb621ad7 JW |
4442 | emit_insn (gen_cmpsf (operands[1], reg1)); |
4443 | emit_jump_insn (gen_bge (label1)); | |
8ef30996 | 4444 | |
bb621ad7 | 4445 | emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1])); |
c5c76735 JL |
4446 | emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, |
4447 | gen_rtx_LABEL_REF (VOIDmode, label2))); | |
bb621ad7 | 4448 | emit_barrier (); |
8ef30996 | 4449 | |
bb621ad7 | 4450 | emit_label (label1); |
c5c76735 | 4451 | emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); |
3a6ee9f4 | 4452 | emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); |
bb621ad7 | 4453 | emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); |
8ef30996 | 4454 | |
bb621ad7 JW |
4455 | emit_insn (gen_fix_truncsfdi2 (operands[0], reg2)); |
4456 | emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); | |
8ef30996 | 4457 | |
bb621ad7 | 4458 | emit_label (label2); |
8ef30996 | 4459 | |
bb621ad7 JW |
4460 | /* allow REG_NOTES to be set on last insn (labels don't have enough |
4461 | fields, and can't be used for REG_NOTES anyway). */ | |
c5c76735 | 4462 | emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); |
bb621ad7 | 4463 | DONE; |
8ef30996 | 4464 | } |
bb621ad7 | 4465 | }") |
8ef30996 | 4466 | |
bb621ad7 JW |
4467 | \f |
4468 | ;; | |
4469 | ;; .................... | |
4470 | ;; | |
4471 | ;; DATA MOVEMENT | |
4472 | ;; | |
4473 | ;; .................... | |
8ef30996 | 4474 | |
c5563e11 JW |
4475 | ;; Bit field extract patterns which use lwl/lwr. |
4476 | ||
c5563e11 JW |
4477 | ;; ??? There could be HImode variants for the ulh/ulhu/ush macros. |
4478 | ;; It isn't clear whether this will give better code. | |
4479 | ||
0d8e55d8 | 4480 | ;; Only specify the mode operand 1, the rest are assumed to be word_mode. |
c5563e11 | 4481 | (define_expand "extv" |
0d8e55d8 JL |
4482 | [(set (match_operand 0 "register_operand" "") |
4483 | (sign_extract (match_operand:QI 1 "memory_operand" "") | |
4484 | (match_operand 2 "immediate_operand" "") | |
4485 | (match_operand 3 "immediate_operand" "")))] | |
2bcb2ab3 | 4486 | "!TARGET_MIPS16" |
c5563e11 JW |
4487 | " |
4488 | { | |
0d8e55d8 JL |
4489 | /* If the field does not start on a byte boundary, then fail. */ |
4490 | if (INTVAL (operands[3]) % 8 != 0) | |
4491 | FAIL; | |
4492 | ||
4493 | /* MIPS I and MIPS II can only handle a 32bit field. */ | |
4494 | if (!TARGET_64BIT && INTVAL (operands[2]) != 32) | |
4495 | FAIL; | |
4496 | ||
4497 | /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ | |
4498 | if (TARGET_64BIT | |
4499 | && INTVAL (operands[2]) != 64 | |
4500 | && INTVAL (operands[2]) != 32) | |
c5563e11 JW |
4501 | FAIL; |
4502 | ||
4503 | /* This can happen for a 64 bit target, when extracting a value from | |
4504 | a 64 bit union member. extract_bit_field doesn't verify that our | |
4505 | source matches the predicate, so we force it to be a MEM here. */ | |
4506 | if (GET_CODE (operands[1]) != MEM) | |
4507 | FAIL; | |
8ef30996 | 4508 | |
4911814e JW |
4509 | /* Change the mode to BLKmode for aliasing purposes. */ |
4510 | operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0)); | |
4511 | ||
0d8e55d8 JL |
4512 | /* Otherwise, emit a l[wd]l/l[wd]r pair to load the value. */ |
4513 | if (INTVAL (operands[2]) == 64) | |
4514 | emit_insn (gen_movdi_uld (operands[0], operands[1])); | |
4515 | else | |
4516 | { | |
4517 | if (TARGET_64BIT) | |
4518 | { | |
4519 | operands[0] = gen_lowpart (SImode, operands[0]); | |
4520 | if (operands[0] == NULL_RTX) | |
4521 | FAIL; | |
4522 | } | |
4523 | emit_insn (gen_movsi_ulw (operands[0], operands[1])); | |
4524 | } | |
c5563e11 JW |
4525 | DONE; |
4526 | }") | |
4527 | ||
0d8e55d8 | 4528 | ;; Only specify the mode operand 1, the rest are assumed to be word_mode. |
c5563e11 | 4529 | (define_expand "extzv" |
0d8e55d8 JL |
4530 | [(set (match_operand 0 "register_operand" "") |
4531 | (zero_extract (match_operand:QI 1 "memory_operand" "") | |
4532 | (match_operand 2 "immediate_operand" "") | |
4533 | (match_operand 3 "immediate_operand" "")))] | |
2bcb2ab3 | 4534 | "!TARGET_MIPS16" |
c5563e11 JW |
4535 | " |
4536 | { | |
0d8e55d8 JL |
4537 | /* If the field does not start on a byte boundary, then fail. */ |
4538 | if (INTVAL (operands[3]) % 8 != 0) | |
4539 | FAIL; | |
4540 | ||
4541 | /* MIPS I and MIPS II can only handle a 32bit field. */ | |
4542 | if (!TARGET_64BIT && INTVAL (operands[2]) != 32) | |
4543 | FAIL; | |
4544 | ||
4545 | /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ | |
4546 | if (TARGET_64BIT | |
4547 | && INTVAL (operands[2]) != 64 | |
4548 | && INTVAL (operands[2]) != 32) | |
c5563e11 JW |
4549 | FAIL; |
4550 | ||
4551 | /* This can happen for a 64 bit target, when extracting a value from | |
4552 | a 64 bit union member. extract_bit_field doesn't verify that our | |
4553 | source matches the predicate, so we force it to be a MEM here. */ | |
4554 | if (GET_CODE (operands[1]) != MEM) | |
4555 | FAIL; | |
4556 | ||
4911814e JW |
4557 | /* Change the mode to BLKmode for aliasing purposes. */ |
4558 | operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0)); | |
4559 | ||
c5563e11 | 4560 | /* Otherwise, emit a lwl/lwr pair to load the value. */ |
0d8e55d8 JL |
4561 | if (INTVAL (operands[2]) == 64) |
4562 | emit_insn (gen_movdi_uld (operands[0], operands[1])); | |
4563 | else | |
4564 | { | |
4565 | if (TARGET_64BIT) | |
4566 | { | |
4567 | operands[0] = gen_lowpart (SImode, operands[0]); | |
4568 | if (operands[0] == NULL_RTX) | |
4569 | FAIL; | |
4570 | } | |
4571 | emit_insn (gen_movsi_ulw (operands[0], operands[1])); | |
4572 | } | |
c5563e11 JW |
4573 | DONE; |
4574 | }") | |
4575 | ||
0d8e55d8 | 4576 | ;; Only specify the mode operands 0, the rest are assumed to be word_mode. |
c5563e11 | 4577 | (define_expand "insv" |
0d8e55d8 JL |
4578 | [(set (zero_extract (match_operand:QI 0 "memory_operand" "") |
4579 | (match_operand 1 "immediate_operand" "") | |
4580 | (match_operand 2 "immediate_operand" "")) | |
4581 | (match_operand 3 "register_operand" ""))] | |
2bcb2ab3 | 4582 | "!TARGET_MIPS16" |
c5563e11 JW |
4583 | " |
4584 | { | |
0d8e55d8 JL |
4585 | /* If the field does not start on a byte boundary, then fail. */ |
4586 | if (INTVAL (operands[2]) % 8 != 0) | |
4587 | FAIL; | |
4588 | ||
4589 | /* MIPS I and MIPS II can only handle a 32bit field. */ | |
4590 | if (!TARGET_64BIT && INTVAL (operands[1]) != 32) | |
4591 | FAIL; | |
4592 | ||
4593 | /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ | |
4594 | if (TARGET_64BIT | |
4595 | && INTVAL (operands[1]) != 64 | |
4596 | && INTVAL (operands[1]) != 32) | |
c5563e11 JW |
4597 | FAIL; |
4598 | ||
4599 | /* This can happen for a 64 bit target, when storing into a 32 bit union | |
4600 | member. store_bit_field doesn't verify that our target matches the | |
4601 | predicate, so we force it to be a MEM here. */ | |
4602 | if (GET_CODE (operands[0]) != MEM) | |
4603 | FAIL; | |
4604 | ||
4911814e JW |
4605 | /* Change the mode to BLKmode for aliasing purposes. */ |
4606 | operands[0] = change_address (operands[0], BLKmode, XEXP (operands[0], 0)); | |
4607 | ||
0d8e55d8 JL |
4608 | /* Otherwise, emit a s[wd]l/s[wd]r pair to load the value. */ |
4609 | if (INTVAL (operands[1]) == 64) | |
4610 | emit_insn (gen_movdi_usd (operands[0], operands[3])); | |
4611 | else | |
4612 | { | |
4613 | if (TARGET_64BIT) | |
4614 | { | |
4615 | operands[3] = gen_lowpart (SImode, operands[3]); | |
4616 | if (operands[3] == NULL_RTX) | |
4617 | FAIL; | |
4618 | } | |
4619 | emit_insn (gen_movsi_usw (operands[0], operands[3])); | |
4620 | } | |
c5563e11 JW |
4621 | DONE; |
4622 | }") | |
4623 | ||
4624 | ;; unaligned word moves generated by the bit field patterns | |
4625 | ||
4626 | (define_insn "movsi_ulw" | |
4627 | [(set (match_operand:SI 0 "register_operand" "=&d,&d") | |
4911814e | 4628 | (unspec:SI [(match_operand:BLK 1 "general_operand" "R,o")] 0))] |
2bcb2ab3 | 4629 | "!TARGET_MIPS16" |
c5563e11 JW |
4630 | "* |
4631 | { | |
4632 | rtx offset = const0_rtx; | |
4633 | rtx addr = XEXP (operands[1], 0); | |
4634 | rtx mem_addr = eliminate_constant_term (addr, &offset); | |
e2fe6aba | 4635 | const char *ret; |
c5563e11 JW |
4636 | |
4637 | if (TARGET_STATS) | |
4638 | mips_count_memory_refs (operands[1], 2); | |
4639 | ||
4640 | /* The stack/frame pointers are always aligned, so we can convert | |
4641 | to the faster lw if we are referencing an aligned stack location. */ | |
4642 | ||
4643 | if ((INTVAL (offset) & 3) == 0 | |
4644 | && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) | |
4645 | ret = \"lw\\t%0,%1\"; | |
4646 | else | |
4647 | ret = \"ulw\\t%0,%1\"; | |
4648 | ||
4649 | return mips_fill_delay_slot (ret, DELAY_LOAD, operands, insn); | |
4650 | }" | |
4651 | [(set_attr "type" "load,load") | |
4652 | (set_attr "mode" "SI") | |
0ff83799 | 4653 | (set_attr "length" "8,16")]) |
c5563e11 JW |
4654 | |
4655 | (define_insn "movsi_usw" | |
4911814e JW |
4656 | [(set (match_operand:BLK 0 "memory_operand" "=R,o") |
4657 | (unspec:BLK [(match_operand:SI 1 "reg_or_0_operand" "dJ,dJ")] 1))] | |
2bcb2ab3 | 4658 | "!TARGET_MIPS16" |
c5563e11 JW |
4659 | "* |
4660 | { | |
4661 | rtx offset = const0_rtx; | |
4662 | rtx addr = XEXP (operands[0], 0); | |
4663 | rtx mem_addr = eliminate_constant_term (addr, &offset); | |
4664 | ||
4665 | if (TARGET_STATS) | |
4666 | mips_count_memory_refs (operands[0], 2); | |
4667 | ||
4668 | /* The stack/frame pointers are always aligned, so we can convert | |
4669 | to the faster sw if we are referencing an aligned stack location. */ | |
4670 | ||
4671 | if ((INTVAL (offset) & 3) == 0 | |
4672 | && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) | |
7ca3e713 | 4673 | return \"sw\\t%z1,%0\"; |
c5563e11 JW |
4674 | |
4675 | return \"usw\\t%z1,%0\"; | |
4676 | }" | |
4677 | [(set_attr "type" "store") | |
4678 | (set_attr "mode" "SI") | |
0ff83799 | 4679 | (set_attr "length" "8,16")]) |
ed50ab35 | 4680 | |
0d8e55d8 JL |
4681 | ;; Bit field extract patterns which use ldl/ldr. |
4682 | ||
4683 | ;; unaligned double word moves generated by the bit field patterns | |
4684 | ||
4685 | (define_insn "movdi_uld" | |
4686 | [(set (match_operand:DI 0 "register_operand" "=&d,&d") | |
4687 | (unspec:DI [(match_operand:BLK 1 "general_operand" "R,o")] 0))] | |
4688 | "" | |
4689 | "* | |
4690 | { | |
4691 | rtx offset = const0_rtx; | |
4692 | rtx addr = XEXP (operands[1], 0); | |
4693 | rtx mem_addr = eliminate_constant_term (addr, &offset); | |
e2fe6aba | 4694 | const char *ret; |
0d8e55d8 JL |
4695 | |
4696 | if (TARGET_STATS) | |
4697 | mips_count_memory_refs (operands[1], 2); | |
4698 | ||
4699 | /* The stack/frame pointers are always aligned, so we can convert | |
4700 | to the faster lw if we are referencing an aligned stack location. */ | |
4701 | ||
4702 | if ((INTVAL (offset) & 7) == 0 | |
4703 | && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) | |
4704 | ret = \"ld\\t%0,%1\"; | |
4705 | else | |
4706 | ret = \"uld\\t%0,%1\"; | |
4707 | ||
4708 | return mips_fill_delay_slot (ret, DELAY_LOAD, operands, insn); | |
4709 | }" | |
4710 | [(set_attr "type" "load,load") | |
4711 | (set_attr "mode" "SI") | |
0ff83799 | 4712 | (set_attr "length" "8,16")]) |
0d8e55d8 JL |
4713 | |
4714 | (define_insn "movdi_usd" | |
4715 | [(set (match_operand:BLK 0 "memory_operand" "=R,o") | |
4716 | (unspec:BLK [(match_operand:DI 1 "reg_or_0_operand" "dJ,dJ")] 1))] | |
4717 | "" | |
4718 | "* | |
4719 | { | |
4720 | rtx offset = const0_rtx; | |
4721 | rtx addr = XEXP (operands[0], 0); | |
4722 | rtx mem_addr = eliminate_constant_term (addr, &offset); | |
4723 | ||
4724 | if (TARGET_STATS) | |
4725 | mips_count_memory_refs (operands[0], 2); | |
4726 | ||
4727 | /* The stack/frame pointers are always aligned, so we can convert | |
4728 | to the faster sw if we are referencing an aligned stack location. */ | |
4729 | ||
4730 | if ((INTVAL (offset) & 7) == 0 | |
4731 | && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) | |
4732 | return \"sd\\t%1,%0\"; | |
4733 | ||
4734 | return \"usd\\t%z1,%0\"; | |
4735 | }" | |
4736 | [(set_attr "type" "store") | |
4737 | (set_attr "mode" "SI") | |
0ff83799 | 4738 | (set_attr "length" "8,16")]) |
0d8e55d8 | 4739 | |
aa4e54c4 JW |
4740 | ;; These two patterns support loading addresses with two instructions instead |
4741 | ;; of using the macro instruction la. | |
4742 | ||
4743 | ;; ??? mips_move_1word has support for HIGH, so this pattern may be | |
4744 | ;; unnecessary. | |
4745 | ||
4746 | (define_insn "high" | |
4747 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4748 | (high:SI (match_operand:SI 1 "immediate_operand" "")))] | |
2bcb2ab3 | 4749 | "mips_split_addresses && !TARGET_MIPS16" |
aa4e54c4 | 4750 | "lui\\t%0,%%hi(%1) # high" |
0ff83799 | 4751 | [(set_attr "type" "move")]) |
aa4e54c4 JW |
4752 | |
4753 | (define_insn "low" | |
4754 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4755 | (lo_sum:SI (match_operand:SI 1 "register_operand" "r") | |
4756 | (match_operand:SI 2 "immediate_operand" "")))] | |
2bcb2ab3 | 4757 | "mips_split_addresses && !TARGET_MIPS16" |
aa4e54c4 JW |
4758 | "addiu\\t%0,%1,%%lo(%2) # low" |
4759 | [(set_attr "type" "arith") | |
0ff83799 | 4760 | (set_attr "mode" "SI")]) |
aa4e54c4 | 4761 | |
8ef30996 MM |
4762 | ;; 64-bit integer moves |
4763 | ||
4764 | ;; Unlike most other insns, the move insns can't be split with | |
4765 | ;; different predicates, because register spilling and other parts of | |
4766 | ;; the compiler, have memoized the insn number already. | |
4767 | ||
ed50ab35 MM |
4768 | (define_expand "movdi" |
4769 | [(set (match_operand:DI 0 "nonimmediate_operand" "") | |
4770 | (match_operand:DI 1 "general_operand" ""))] | |
4771 | "" | |
4772 | " | |
4773 | { | |
aa4e54c4 JW |
4774 | if (mips_split_addresses && mips_check_split (operands[1], DImode)) |
4775 | { | |
4776 | enum machine_mode mode = GET_MODE (operands[0]); | |
4777 | rtx tem = ((reload_in_progress | reload_completed) | |
4778 | ? operands[0] : gen_reg_rtx (mode)); | |
4779 | ||
c5c76735 JL |
4780 | emit_insn (gen_rtx_SET (VOIDmode, tem, |
4781 | gen_rtx_HIGH (mode, operands[1]))); | |
aa4e54c4 | 4782 | |
c5c76735 | 4783 | operands[1] = gen_rtx_LO_SUM (mode, tem, operands[1]); |
aa4e54c4 JW |
4784 | } |
4785 | ||
e19ff60f JW |
4786 | /* If we are generating embedded PIC code, and we are referring to a |
4787 | symbol in the .text section, we must use an offset from the start | |
4788 | of the function. */ | |
4789 | if (TARGET_EMBEDDED_PIC | |
4790 | && (GET_CODE (operands[1]) == LABEL_REF | |
4791 | || (GET_CODE (operands[1]) == SYMBOL_REF | |
4792 | && ! SYMBOL_REF_FLAG (operands[1])))) | |
4793 | { | |
4794 | rtx temp; | |
4795 | ||
4796 | temp = embedded_pic_offset (operands[1]); | |
c5c76735 JL |
4797 | temp = gen_rtx_PLUS (Pmode, embedded_pic_fnaddr_rtx, |
4798 | force_reg (DImode, temp)); | |
e19ff60f JW |
4799 | emit_move_insn (operands[0], force_reg (DImode, temp)); |
4800 | DONE; | |
4801 | } | |
4802 | ||
4803 | /* If operands[1] is a constant address illegal for pic, then we need to | |
4804 | handle it just like LEGITIMIZE_ADDRESS does. */ | |
4805 | if (flag_pic && pic_address_needs_scratch (operands[1])) | |
4806 | { | |
4807 | rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0)); | |
4808 | rtx temp2 = XEXP (XEXP (operands[1], 0), 1); | |
4809 | ||
4810 | if (! SMALL_INT (temp2)) | |
4811 | temp2 = force_reg (DImode, temp2); | |
4812 | ||
c5c76735 | 4813 | emit_move_insn (operands[0], gen_rtx_PLUS (DImode, temp, temp2)); |
e19ff60f JW |
4814 | DONE; |
4815 | } | |
4816 | ||
2bcb2ab3 GK |
4817 | /* On the mips16, we can handle a GP relative reference by adding in |
4818 | $gp. We need to check the name to see whether this is a string | |
4819 | constant. */ | |
4820 | if (TARGET_MIPS16 | |
4821 | && register_operand (operands[0], DImode) | |
4822 | && GET_CODE (operands[1]) == SYMBOL_REF | |
4823 | && SYMBOL_REF_FLAG (operands[1])) | |
4824 | { | |
3cce094d | 4825 | const char *name = XSTR (operands[1], 0); |
2bcb2ab3 GK |
4826 | |
4827 | if (name[0] != '*' | |
4828 | || strncmp (name + 1, LOCAL_LABEL_PREFIX, | |
4829 | sizeof LOCAL_LABEL_PREFIX - 1) != 0) | |
4830 | { | |
4831 | rtx base_reg; | |
4832 | ||
4833 | if (reload_in_progress || reload_completed) | |
4834 | { | |
4835 | /* In movsi we use the constant table here. However, in | |
4836 | this case, we're better off copying $28 into a | |
4837 | register and adding, because the constant table entry | |
4838 | would be 8 bytes. */ | |
4839 | base_reg = operands[0]; | |
4840 | emit_move_insn (base_reg, | |
4841 | gen_rtx (CONST, DImode, | |
4842 | gen_rtx (REG, DImode, | |
4843 | GP_REG_FIRST + 28))); | |
4844 | } | |
4845 | else | |
4846 | { | |
4847 | base_reg = gen_reg_rtx (Pmode); | |
4848 | emit_move_insn (base_reg, mips16_gp_pseudo_reg ()); | |
4849 | } | |
4850 | ||
4851 | emit_move_insn (operands[0], | |
7e4e0956 | 4852 | gen_rtx (PLUS, Pmode, base_reg, |
2bcb2ab3 GK |
4853 | mips16_gp_offset (operands[1]))); |
4854 | DONE; | |
4855 | } | |
4856 | } | |
4857 | ||
ed50ab35 MM |
4858 | if ((reload_in_progress | reload_completed) == 0 |
4859 | && !register_operand (operands[0], DImode) | |
4860 | && !register_operand (operands[1], DImode) | |
2bcb2ab3 | 4861 | && (TARGET_MIPS16 |
6e92f4b6 KG |
4862 | || ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) |
4863 | && operands[1] != CONST0_RTX (DImode)))) | |
ed50ab35 MM |
4864 | { |
4865 | rtx temp = force_reg (DImode, operands[1]); | |
4866 | emit_move_insn (operands[0], temp); | |
4867 | DONE; | |
4868 | } | |
4869 | }") | |
4870 | ||
2bcb2ab3 GK |
4871 | ;; For mips16, we need a special case to handle storing $31 into |
4872 | ;; memory, since we don't have a constraint to match $31. This | |
4873 | ;; instruction can be generated by save_restore_insns. | |
4874 | ||
4875 | (define_insn "" | |
0e7e9155 | 4876 | [(set (match_operand:DI 0 "memory_operand" "=R,m") |
2bcb2ab3 GK |
4877 | (reg:DI 31))] |
4878 | "TARGET_MIPS16 && TARGET_64BIT" | |
4879 | "* | |
4880 | { | |
4881 | operands[1] = gen_rtx (REG, DImode, 31); | |
4882 | return mips_move_2words (operands, insn); | |
4883 | }" | |
4884 | [(set_attr "type" "store") | |
4885 | (set_attr "mode" "DI") | |
0ff83799 | 4886 | (set_attr "length" "4,8")]) |
2bcb2ab3 | 4887 | |
ed50ab35 | 4888 | (define_insn "movdi_internal" |
c4eec192 JW |
4889 | [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*x,*d,*x") |
4890 | (match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,J,*x,*d"))] | |
2bcb2ab3 | 4891 | "!TARGET_64BIT && !TARGET_MIPS16 |
bb621ad7 JW |
4892 | && (register_operand (operands[0], DImode) |
4893 | || register_operand (operands[1], DImode) | |
4894 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) | |
4895 | || operands[1] == CONST0_RTX (DImode))" | |
8ef30996 | 4896 | "* return mips_move_2words (operands, insn); " |
c4eec192 | 4897 | [(set_attr "type" "move,arith,load,load,store,store,hilo,hilo,hilo") |
92b4cee1 | 4898 | (set_attr "mode" "DI") |
0ff83799 | 4899 | (set_attr "length" "8,16,8,16,8,16,8,8,8")]) |
8ef30996 | 4900 | |
2bcb2ab3 GK |
4901 | (define_insn "" |
4902 | [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,To,*d") | |
4903 | (match_operand:DI 1 "general_operand" "d,d,y,K,N,R,To,d,d,*x"))] | |
4904 | "!TARGET_64BIT && TARGET_MIPS16 | |
4905 | && (register_operand (operands[0], DImode) | |
4906 | || register_operand (operands[1], DImode))" | |
4907 | "* return mips_move_2words (operands, insn);" | |
4908 | [(set_attr "type" "move,move,move,arith,arith,load,load,store,store,hilo") | |
4909 | (set_attr "mode" "DI") | |
0ff83799 | 4910 | (set_attr "length" "8,8,8,8,12,8,16,8,16,8")]) |
2bcb2ab3 | 4911 | |
8ef30996 MM |
4912 | (define_split |
4913 | [(set (match_operand:DI 0 "register_operand" "") | |
4914 | (match_operand:DI 1 "register_operand" ""))] | |
bb621ad7 | 4915 | "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
8ef30996 MM |
4916 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
4917 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" | |
4918 | ||
4919 | [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) | |
ddef6bc7 | 4920 | (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))] |
8ef30996 MM |
4921 | "") |
4922 | ||
bb621ad7 | 4923 | (define_insn "movdi_internal2" |
c4eec192 JW |
4924 | [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*x,*d,*x,*a") |
4925 | (match_operand:DI 1 "movdi_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,J,*x,*d,*J"))] | |
2bcb2ab3 | 4926 | "TARGET_64BIT && !TARGET_MIPS16 |
bb621ad7 | 4927 | && (register_operand (operands[0], DImode) |
1908a152 | 4928 | || se_register_operand (operands[1], DImode) |
bb621ad7 JW |
4929 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) |
4930 | || operands[1] == CONST0_RTX (DImode))" | |
4931 | "* return mips_move_2words (operands, insn); " | |
c4eec192 | 4932 | [(set_attr "type" "move,load,arith,arith,load,load,store,store,hilo,hilo,hilo,hilo") |
bb621ad7 | 4933 | (set_attr "mode" "DI") |
0ff83799 | 4934 | (set_attr "length" "4,8,4,8,4,8,4,8,4,4,4,8")]) |
225b8835 | 4935 | |
2bcb2ab3 GK |
4936 | (define_insn "" |
4937 | [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,R,m,*d") | |
4938 | (match_operand:DI 1 "movdi_operand" "d,d,y,K,N,s,R,m,d,d,*x"))] | |
4939 | "TARGET_64BIT && TARGET_MIPS16 | |
4940 | && (register_operand (operands[0], DImode) | |
4941 | || se_register_operand (operands[1], DImode))" | |
4942 | "* return mips_move_2words (operands, insn);" | |
4943 | [(set_attr "type" "move,move,move,arith,arith,arith,load,load,store,store,hilo") | |
4944 | (set_attr "mode" "DI") | |
4945 | (set_attr_alternative "length" | |
0ff83799 MM |
4946 | [(const_int 4) |
4947 | (const_int 4) | |
4948 | (const_int 4) | |
2bcb2ab3 | 4949 | (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") |
0ff83799 MM |
4950 | (const_int 4) |
4951 | (const_int 8)) | |
2bcb2ab3 | 4952 | (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") |
0ff83799 MM |
4953 | (const_int 8) |
4954 | (const_int 12)) | |
2bcb2ab3 | 4955 | (if_then_else (match_operand:VOID 1 "m16_usym5_4" "") |
0ff83799 MM |
4956 | (const_int 4) |
4957 | (const_int 8)) | |
4958 | (const_int 4) | |
4959 | (const_int 8) | |
4960 | (const_int 4) | |
4961 | (const_int 8) | |
4962 | (const_int 4)])]) | |
2bcb2ab3 GK |
4963 | |
4964 | ;; On the mips16, we can split ld $r,N($r) into an add and a load, | |
4965 | ;; when the original load is a 4 byte instruction but the add and the | |
4966 | ;; load are 2 2 byte instructions. | |
4967 | ||
4968 | (define_split | |
4969 | [(set (match_operand:DI 0 "register_operand" "") | |
4970 | (mem:DI (plus:DI (match_dup 0) | |
4971 | (match_operand:DI 1 "const_int_operand" ""))))] | |
4972 | "TARGET_64BIT && TARGET_MIPS16 && reload_completed | |
4973 | && GET_CODE (operands[0]) == REG | |
4974 | && M16_REG_P (REGNO (operands[0])) | |
4975 | && GET_CODE (operands[1]) == CONST_INT | |
4976 | && ((INTVAL (operands[1]) < 0 | |
4977 | && INTVAL (operands[1]) >= -0x10) | |
4978 | || (INTVAL (operands[1]) >= 32 * 8 | |
4979 | && INTVAL (operands[1]) <= 31 * 8 + 0x8) | |
4980 | || (INTVAL (operands[1]) >= 0 | |
4981 | && INTVAL (operands[1]) < 32 * 8 | |
4982 | && (INTVAL (operands[1]) & 7) != 0))" | |
4983 | [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) | |
4984 | (set (match_dup 0) (mem:DI (plus:DI (match_dup 0) (match_dup 2))))] | |
4985 | " | |
4986 | { | |
4987 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
4988 | ||
4989 | if (val < 0) | |
4990 | operands[2] = GEN_INT (0); | |
4991 | else if (val >= 32 * 8) | |
4992 | { | |
4993 | int off = val & 7; | |
4994 | ||
4995 | operands[1] = GEN_INT (0x8 + off); | |
4996 | operands[2] = GEN_INT (val - off - 0x8); | |
4997 | } | |
4998 | else | |
4999 | { | |
5000 | int off = val & 7; | |
5001 | ||
5002 | operands[1] = GEN_INT (off); | |
5003 | operands[2] = GEN_INT (val - off); | |
5004 | } | |
5005 | }") | |
5006 | ||
225b8835 ILT |
5007 | ;; Handle input reloads in DImode. |
5008 | ;; This is mainly to handle reloading HILO_REGNUM. Note that we may | |
5009 | ;; see it as the source or the destination, depending upon which way | |
5010 | ;; reload handles the instruction. | |
5011 | ;; Making the second operand TImode is a trick. The compiler may | |
5012 | ;; reuse the same register for operand 0 and operand 2. Using TImode | |
5013 | ;; gives us two registers, so we can always use the one which is not | |
5014 | ;; used. | |
5015 | ||
5016 | (define_expand "reload_indi" | |
5017 | [(set (match_operand:DI 0 "register_operand" "=b") | |
9ec36da5 | 5018 | (match_operand:DI 1 "" "b")) |
225b8835 ILT |
5019 | (clobber (match_operand:TI 2 "register_operand" "=&d"))] |
5020 | "TARGET_64BIT" | |
5021 | " | |
5022 | { | |
c5c76735 JL |
5023 | rtx scratch = gen_rtx_REG (DImode, |
5024 | (REGNO (operands[0]) == REGNO (operands[2]) | |
5025 | ? REGNO (operands[2]) + 1 | |
5026 | : REGNO (operands[2]))); | |
225b8835 ILT |
5027 | |
5028 | if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM) | |
5029 | { | |
5030 | if (GET_CODE (operands[1]) == MEM) | |
5031 | { | |
404e4854 | 5032 | rtx memword, offword, hi_word, lo_word; |
9ec36da5 JL |
5033 | rtx addr = find_replacement (&XEXP (operands[1], 0)); |
5034 | rtx op1 = change_address (operands[1], VOIDmode, addr); | |
225b8835 | 5035 | |
c5c76735 | 5036 | scratch = gen_rtx_REG (SImode, REGNO (scratch)); |
9ec36da5 JL |
5037 | memword = change_address (op1, SImode, NULL_RTX); |
5038 | offword = change_address (adj_offsettable_operand (op1, 4), | |
225b8835 ILT |
5039 | SImode, NULL_RTX); |
5040 | if (BYTES_BIG_ENDIAN) | |
5041 | { | |
404e4854 KG |
5042 | hi_word = memword; |
5043 | lo_word = offword; | |
225b8835 ILT |
5044 | } |
5045 | else | |
5046 | { | |
404e4854 KG |
5047 | hi_word = offword; |
5048 | lo_word = memword; | |
225b8835 | 5049 | } |
404e4854 | 5050 | emit_move_insn (scratch, hi_word); |
c5c76735 | 5051 | emit_move_insn (gen_rtx_REG (SImode, 64), scratch); |
404e4854 | 5052 | emit_move_insn (scratch, lo_word); |
225b8835 | 5053 | emit_move_insn (gen_rtx (REG, SImode, 65), scratch); |
839366dd | 5054 | emit_insn (gen_rtx_USE (VOIDmode, operands[0])); |
225b8835 ILT |
5055 | } |
5056 | else | |
5057 | { | |
5058 | emit_insn (gen_ashrdi3 (scratch, operands[1], GEN_INT (32))); | |
c5c76735 | 5059 | emit_insn (gen_movdi (gen_rtx_REG (DImode, 64), scratch)); |
225b8835 ILT |
5060 | emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32))); |
5061 | emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32))); | |
5062 | emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch)); | |
839366dd | 5063 | emit_insn (gen_rtx_USE (VOIDmode, operands[0])); |
225b8835 ILT |
5064 | } |
5065 | DONE; | |
5066 | } | |
5067 | if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == HILO_REGNUM) | |
5068 | { | |
c5c76735 | 5069 | emit_insn (gen_movdi (scratch, gen_rtx_REG (DImode, 65))); |
225b8835 ILT |
5070 | emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32))); |
5071 | emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32))); | |
c5c76735 | 5072 | emit_insn (gen_movdi (operands[0], gen_rtx_REG (DImode, 64))); |
225b8835 ILT |
5073 | emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32))); |
5074 | emit_insn (gen_iordi3 (operands[0], operands[0], scratch)); | |
839366dd | 5075 | emit_insn (gen_rtx_USE (VOIDmode, operands[1])); |
225b8835 ILT |
5076 | DONE; |
5077 | } | |
5078 | /* This handles moves between a float register and HI/LO. */ | |
5079 | emit_move_insn (scratch, operands[1]); | |
5080 | emit_move_insn (operands[0], scratch); | |
5081 | DONE; | |
5082 | }") | |
bb621ad7 | 5083 | |
225b8835 ILT |
5084 | ;; Handle output reloads in DImode. |
5085 | ||
cf877a42 JW |
5086 | ;; Reloading HILO_REG in MIPS16 mode requires two scratch registers, so we |
5087 | ;; use a TImode scratch reg. | |
5088 | ||
225b8835 | 5089 | (define_expand "reload_outdi" |
9ec36da5 | 5090 | [(set (match_operand:DI 0 "" "=b") |
1908a152 | 5091 | (match_operand:DI 1 "se_register_operand" "b")) |
cf877a42 | 5092 | (clobber (match_operand:TI 2 "register_operand" "=&d"))] |
225b8835 ILT |
5093 | "TARGET_64BIT" |
5094 | " | |
5095 | { | |
cf877a42 JW |
5096 | rtx scratch = gen_rtx_REG (DImode, REGNO (operands[2])); |
5097 | ||
225b8835 ILT |
5098 | if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM) |
5099 | { | |
cf877a42 JW |
5100 | emit_insn (gen_ashrdi3 (scratch, operands[1], GEN_INT (32))); |
5101 | emit_insn (gen_movdi (gen_rtx (REG, DImode, 64), scratch)); | |
5102 | emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32))); | |
5103 | emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32))); | |
5104 | emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch)); | |
839366dd | 5105 | emit_insn (gen_rtx_USE (VOIDmode, operands[0])); |
225b8835 ILT |
5106 | DONE; |
5107 | } | |
5108 | if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == HILO_REGNUM) | |
5109 | { | |
5110 | if (GET_CODE (operands[0]) == MEM) | |
5111 | { | |
404e4854 | 5112 | rtx scratch, memword, offword, hi_word, lo_word; |
9ec36da5 JL |
5113 | rtx addr = find_replacement (&XEXP (operands[0], 0)); |
5114 | rtx op0 = change_address (operands[0], VOIDmode, addr); | |
225b8835 | 5115 | |
c5c76735 | 5116 | scratch = gen_rtx_REG (SImode, REGNO (operands[2])); |
9ec36da5 JL |
5117 | memword = change_address (op0, SImode, NULL_RTX); |
5118 | offword = change_address (adj_offsettable_operand (op0, 4), | |
225b8835 ILT |
5119 | SImode, NULL_RTX); |
5120 | if (BYTES_BIG_ENDIAN) | |
5121 | { | |
404e4854 KG |
5122 | hi_word = memword; |
5123 | lo_word = offword; | |
225b8835 ILT |
5124 | } |
5125 | else | |
5126 | { | |
404e4854 KG |
5127 | hi_word = offword; |
5128 | lo_word = memword; | |
225b8835 | 5129 | } |
c5c76735 | 5130 | emit_move_insn (scratch, gen_rtx_REG (SImode, 64)); |
404e4854 | 5131 | emit_move_insn (hi_word, scratch); |
c5c76735 | 5132 | emit_move_insn (scratch, gen_rtx_REG (SImode, 65)); |
404e4854 | 5133 | emit_move_insn (lo_word, scratch); |
839366dd | 5134 | emit_insn (gen_rtx_USE (VOIDmode, operands[1])); |
225b8835 | 5135 | } |
cf877a42 JW |
5136 | else if (TARGET_MIPS16 && ! M16_REG_P (REGNO (operands[0]))) |
5137 | { | |
5138 | /* Handle the case where operand[0] is not a 'd' register, | |
5139 | and hence we can not directly move from the HILO register | |
5140 | into it. */ | |
5141 | rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); | |
5142 | emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65))); | |
5143 | emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32))); | |
5144 | emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32))); | |
5145 | emit_insn (gen_movdi (scratch2, gen_rtx (REG, DImode, 64))); | |
5146 | emit_insn (gen_ashldi3 (scratch2, scratch2, GEN_INT (32))); | |
5147 | emit_insn (gen_iordi3 (scratch, scratch, scratch2)); | |
5148 | emit_insn (gen_movdi (operands[0], scratch)); | |
839366dd | 5149 | emit_insn (gen_rtx_USE (VOIDmode, operands[1])); |
cf877a42 | 5150 | } |
225b8835 ILT |
5151 | else |
5152 | { | |
cf877a42 JW |
5153 | emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65))); |
5154 | emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32))); | |
5155 | emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32))); | |
225b8835 ILT |
5156 | emit_insn (gen_movdi (operands[0], gen_rtx (REG, DImode, 64))); |
5157 | emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32))); | |
cf877a42 | 5158 | emit_insn (gen_iordi3 (operands[0], operands[0], scratch)); |
839366dd | 5159 | emit_insn (gen_rtx_USE (VOIDmode, operands[1])); |
225b8835 ILT |
5160 | } |
5161 | DONE; | |
5162 | } | |
5163 | /* This handles moves between a float register and HI/LO. */ | |
cf877a42 JW |
5164 | emit_move_insn (scratch, operands[1]); |
5165 | emit_move_insn (operands[0], scratch); | |
225b8835 ILT |
5166 | DONE; |
5167 | }") | |
8ef30996 MM |
5168 | |
5169 | ;; 32-bit Integer moves | |
5170 | ||
5171 | (define_split | |
5172 | [(set (match_operand:SI 0 "register_operand" "") | |
5173 | (match_operand:SI 1 "large_int" ""))] | |
2bcb2ab3 | 5174 | "!TARGET_DEBUG_D_MODE && !TARGET_MIPS16" |
8ef30996 MM |
5175 | [(set (match_dup 0) |
5176 | (match_dup 2)) | |
5177 | (set (match_dup 0) | |
5178 | (ior:SI (match_dup 0) | |
5179 | (match_dup 3)))] | |
5180 | " | |
5181 | { | |
3a6ee9f4 MM |
5182 | operands[2] = GEN_INT (INTVAL (operands[1]) & BITMASK_UPPER16); |
5183 | operands[3] = GEN_INT (INTVAL (operands[1]) & BITMASK_LOWER16); | |
8ef30996 MM |
5184 | }") |
5185 | ||
5186 | ;; Unlike most other insns, the move insns can't be split with | |
5187 | ;; different predicates, because register spilling and other parts of | |
5188 | ;; the compiler, have memoized the insn number already. | |
5189 | ||
f3b39eba MM |
5190 | (define_expand "movsi" |
5191 | [(set (match_operand:SI 0 "nonimmediate_operand" "") | |
5192 | (match_operand:SI 1 "general_operand" ""))] | |
5193 | "" | |
ed50ab35 MM |
5194 | " |
5195 | { | |
aa4e54c4 JW |
5196 | if (mips_split_addresses && mips_check_split (operands[1], SImode)) |
5197 | { | |
5198 | enum machine_mode mode = GET_MODE (operands[0]); | |
5199 | rtx tem = ((reload_in_progress | reload_completed) | |
5200 | ? operands[0] : gen_reg_rtx (mode)); | |
5201 | ||
c5c76735 JL |
5202 | emit_insn (gen_rtx_SET (VOIDmode, tem, |
5203 | gen_rtx_HIGH (mode, operands[1]))); | |
aa4e54c4 | 5204 | |
c5c76735 | 5205 | operands[1] = gen_rtx_LO_SUM (mode, tem, operands[1]); |
aa4e54c4 JW |
5206 | } |
5207 | ||
92544bdf ILT |
5208 | /* If we are generating embedded PIC code, and we are referring to a |
5209 | symbol in the .text section, we must use an offset from the start | |
5210 | of the function. */ | |
5211 | if (TARGET_EMBEDDED_PIC | |
5212 | && (GET_CODE (operands[1]) == LABEL_REF | |
5213 | || (GET_CODE (operands[1]) == SYMBOL_REF | |
5214 | && ! SYMBOL_REF_FLAG (operands[1])))) | |
5215 | { | |
5216 | rtx temp; | |
5217 | ||
5218 | temp = embedded_pic_offset (operands[1]); | |
c5c76735 JL |
5219 | temp = gen_rtx_PLUS (Pmode, embedded_pic_fnaddr_rtx, |
5220 | force_reg (SImode, temp)); | |
92544bdf ILT |
5221 | emit_move_insn (operands[0], force_reg (SImode, temp)); |
5222 | DONE; | |
5223 | } | |
5224 | ||
3826a3da | 5225 | /* If operands[1] is a constant address invalid for pic, then we need to |
5a5b76a2 JW |
5226 | handle it just like LEGITIMIZE_ADDRESS does. */ |
5227 | if (flag_pic && pic_address_needs_scratch (operands[1])) | |
5228 | { | |
5229 | rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0)); | |
5230 | rtx temp2 = XEXP (XEXP (operands[1], 0), 1); | |
5231 | ||
5232 | if (! SMALL_INT (temp2)) | |
5233 | temp2 = force_reg (SImode, temp2); | |
5234 | ||
c5c76735 | 5235 | emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, temp2)); |
5a5b76a2 JW |
5236 | DONE; |
5237 | } | |
5238 | ||
2bcb2ab3 GK |
5239 | /* On the mips16, we can handle a GP relative reference by adding in |
5240 | $gp. We need to check the name to see whether this is a string | |
5241 | constant. */ | |
5242 | if (TARGET_MIPS16 | |
5243 | && register_operand (operands[0], SImode) | |
5244 | && GET_CODE (operands[1]) == SYMBOL_REF | |
5245 | && SYMBOL_REF_FLAG (operands[1])) | |
5246 | { | |
3cce094d | 5247 | const char *name = XSTR (operands[1], 0); |
2bcb2ab3 GK |
5248 | |
5249 | if (name[0] != '*' | |
5250 | || strncmp (name + 1, LOCAL_LABEL_PREFIX, | |
5251 | sizeof LOCAL_LABEL_PREFIX - 1) != 0) | |
5252 | { | |
5253 | rtx base_reg; | |
5254 | ||
5255 | if (reload_in_progress || reload_completed) | |
5256 | { | |
5257 | /* We need to reload this address. In this case we | |
5258 | aren't going to have a chance to combine loading the | |
5259 | address with the load or store. That means that we | |
5260 | can either generate a 2 byte move followed by a 4 | |
5261 | byte addition, or a 2 byte load with a 4 byte entry | |
5262 | in the constant table. Since the entry in the | |
5263 | constant table might be shared, we're better off, on | |
5264 | average, loading the address from the constant table. */ | |
5265 | emit_move_insn (operands[0], | |
5266 | force_const_mem (SImode, operands[1])); | |
5267 | DONE; | |
5268 | } | |
5269 | ||
5270 | base_reg = gen_reg_rtx (Pmode); | |
5271 | emit_move_insn (base_reg, mips16_gp_pseudo_reg ()); | |
5272 | ||
5273 | emit_move_insn (operands[0], | |
7e4e0956 | 5274 | gen_rtx (PLUS, Pmode, base_reg, |
2bcb2ab3 GK |
5275 | mips16_gp_offset (operands[1]))); |
5276 | DONE; | |
5277 | } | |
5278 | } | |
5279 | ||
ed50ab35 MM |
5280 | if ((reload_in_progress | reload_completed) == 0 |
5281 | && !register_operand (operands[0], SImode) | |
5282 | && !register_operand (operands[1], SImode) | |
2bcb2ab3 GK |
5283 | && (TARGET_MIPS16 |
5284 | || GET_CODE (operands[1]) != CONST_INT | |
5285 | || INTVAL (operands[1]) != 0)) | |
ed50ab35 MM |
5286 | { |
5287 | rtx temp = force_reg (SImode, operands[1]); | |
5288 | emit_move_insn (operands[0], temp); | |
5289 | DONE; | |
5290 | } | |
5291 | }") | |
f3b39eba | 5292 | |
2bcb2ab3 GK |
5293 | ;; For mips16, we need a special case to handle storing $31 into |
5294 | ;; memory, since we don't have a constraint to match $31. This | |
5295 | ;; instruction can be generated by save_restore_insns. | |
5296 | ||
5297 | (define_insn "" | |
0e7e9155 | 5298 | [(set (match_operand:SI 0 "memory_operand" "=R,m") |
2bcb2ab3 GK |
5299 | (reg:SI 31))] |
5300 | "TARGET_MIPS16" | |
5301 | "* | |
5302 | { | |
5303 | operands[1] = gen_rtx (REG, SImode, 31); | |
5304 | return mips_move_1word (operands, insn, FALSE); | |
5305 | }" | |
5306 | [(set_attr "type" "store") | |
5307 | (set_attr "mode" "SI") | |
0ff83799 | 5308 | (set_attr "length" "4,8")]) |
2bcb2ab3 | 5309 | |
0fb5ac6f MM |
5310 | ;; The difference between these two is whether or not ints are allowed |
5311 | ;; in FP registers (off by default, use -mdebugh to enable). | |
5312 | ||
5313 | (define_insn "movsi_internal1" | |
225b8835 | 5314 | [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x,*x,*d,*d") |
c4eec192 | 5315 | (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,J,*d,*x,*a"))] |
2bcb2ab3 | 5316 | "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 |
ed50ab35 MM |
5317 | && (register_operand (operands[0], SImode) |
5318 | || register_operand (operands[1], SImode) | |
5319 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" | |
bb621ad7 | 5320 | "* return mips_move_1word (operands, insn, FALSE);" |
225b8835 | 5321 | [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo,hilo,hilo") |
92b4cee1 | 5322 | (set_attr "mode" "SI") |
0ff83799 | 5323 | (set_attr "length" "4,8,4,8,4,8,4,8,4,4,4,4,8,4,8,4,4,4,4")]) |
8ef30996 | 5324 | |
0fb5ac6f | 5325 | (define_insn "movsi_internal2" |
225b8835 | 5326 | [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*x,*d,*x,*d") |
c4eec192 | 5327 | (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,J,*x,*d,*a"))] |
2bcb2ab3 | 5328 | "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 |
ed50ab35 MM |
5329 | && (register_operand (operands[0], SImode) |
5330 | || register_operand (operands[1], SImode) | |
5331 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" | |
bb621ad7 | 5332 | "* return mips_move_1word (operands, insn, FALSE);" |
225b8835 | 5333 | [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,hilo,hilo,hilo,hilo") |
0fb5ac6f | 5334 | (set_attr "mode" "SI") |
0ff83799 | 5335 | (set_attr "length" "4,8,4,8,4,8,4,8,4,4,4,4,4,4")]) |
0fb5ac6f | 5336 | |
2bcb2ab3 GK |
5337 | ;; This is the mips16 movsi instruction. We accept a small integer as |
5338 | ;; the source if the destination is a GP memory reference. This is | |
5339 | ;; because we want the combine pass to turn adding a GP reference to a | |
5340 | ;; register into a direct GP reference, but the combine pass will pass | |
5341 | ;; in the source as a constant if it finds an equivalent one. If the | |
5342 | ;; instruction is recognized, reload will force the constant back out | |
5343 | ;; into a register. | |
225b8835 | 5344 | |
2bcb2ab3 GK |
5345 | (define_insn "" |
5346 | [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,d,R,m,*d,*d") | |
5347 | (match_operand:SI 1 "move_operand" "d,d,y,S,K,N,s,R,m,d,d,*x,*a"))] | |
5348 | "TARGET_MIPS16 | |
5349 | && (register_operand (operands[0], SImode) | |
5350 | || register_operand (operands[1], SImode) | |
5351 | || (GET_CODE (operands[0]) == MEM | |
5352 | && GET_CODE (XEXP (operands[0], 0)) == PLUS | |
5353 | && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST | |
5354 | && mips16_gp_offset_p (XEXP (XEXP (operands[0], 0), 1)) | |
5355 | && GET_CODE (operands[1]) == CONST_INT | |
5356 | && (SMALL_INT (operands[1]) | |
5357 | || SMALL_INT_UNSIGNED (operands[1]))))" | |
5358 | "* return mips_move_1word (operands, insn, FALSE);" | |
5359 | [(set_attr "type" "move,move,move,load,arith,arith,arith,load,load,store,store,hilo,hilo") | |
5360 | (set_attr "mode" "SI") | |
5361 | (set_attr_alternative "length" | |
0ff83799 MM |
5362 | [(const_int 4) |
5363 | (const_int 4) | |
5364 | (const_int 4) | |
5365 | (const_int 8) | |
2bcb2ab3 | 5366 | (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") |
0ff83799 MM |
5367 | (const_int 4) |
5368 | (const_int 8)) | |
2bcb2ab3 | 5369 | (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") |
0ff83799 MM |
5370 | (const_int 8) |
5371 | (const_int 12)) | |
2bcb2ab3 | 5372 | (if_then_else (match_operand:VOID 1 "m16_usym8_4" "") |
0ff83799 MM |
5373 | (const_int 4) |
5374 | (const_int 8)) | |
5375 | (const_int 4) | |
5376 | (const_int 8) | |
5377 | (const_int 4) | |
5378 | (const_int 8) | |
5379 | (const_int 4) | |
5380 | (const_int 4)])]) | |
2bcb2ab3 GK |
5381 | |
5382 | ;; On the mips16, we can split lw $r,N($r) into an add and a load, | |
5383 | ;; when the original load is a 4 byte instruction but the add and the | |
5384 | ;; load are 2 2 byte instructions. | |
5385 | ||
5386 | (define_split | |
5387 | [(set (match_operand:SI 0 "register_operand" "") | |
5388 | (mem:SI (plus:SI (match_dup 0) | |
5389 | (match_operand:SI 1 "const_int_operand" ""))))] | |
5390 | "TARGET_MIPS16 && reload_completed | |
5391 | && GET_CODE (operands[0]) == REG | |
5392 | && M16_REG_P (REGNO (operands[0])) | |
5393 | && GET_CODE (operands[1]) == CONST_INT | |
5394 | && ((INTVAL (operands[1]) < 0 | |
5395 | && INTVAL (operands[1]) >= -0x80) | |
5396 | || (INTVAL (operands[1]) >= 32 * 4 | |
5397 | && INTVAL (operands[1]) <= 31 * 4 + 0x7c) | |
5398 | || (INTVAL (operands[1]) >= 0 | |
5399 | && INTVAL (operands[1]) < 32 * 4 | |
5400 | && (INTVAL (operands[1]) & 3) != 0))" | |
5401 | [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) | |
5402 | (set (match_dup 0) (mem:SI (plus:SI (match_dup 0) (match_dup 2))))] | |
225b8835 ILT |
5403 | " |
5404 | { | |
2bcb2ab3 GK |
5405 | HOST_WIDE_INT val = INTVAL (operands[1]); |
5406 | ||
5407 | if (val < 0) | |
5408 | operands[2] = GEN_INT (0); | |
5409 | else if (val >= 32 * 4) | |
5410 | { | |
5411 | int off = val & 3; | |
5412 | ||
5413 | operands[1] = GEN_INT (0x7c + off); | |
5414 | operands[2] = GEN_INT (val - off - 0x7c); | |
5415 | } | |
5416 | else | |
5417 | { | |
5418 | int off = val & 3; | |
5419 | ||
5420 | operands[1] = GEN_INT (off); | |
5421 | operands[2] = GEN_INT (val - off); | |
5422 | } | |
5423 | }") | |
5424 | ||
5425 | ;; On the mips16, we can split a load of certain constants into a load | |
5426 | ;; and an add. This turns a 4 byte instruction into 2 2 byte | |
5427 | ;; instructions. | |
5428 | ||
5429 | (define_split | |
5430 | [(set (match_operand:SI 0 "register_operand" "") | |
5431 | (match_operand:SI 1 "const_int_operand" ""))] | |
5432 | "TARGET_MIPS16 && reload_completed | |
5433 | && GET_CODE (operands[0]) == REG | |
5434 | && M16_REG_P (REGNO (operands[0])) | |
5435 | && GET_CODE (operands[1]) == CONST_INT | |
5436 | && INTVAL (operands[1]) >= 0x100 | |
5437 | && INTVAL (operands[1]) <= 0xff + 0x7f" | |
5438 | [(set (match_dup 0) (match_dup 1)) | |
5439 | (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] | |
5440 | " | |
5441 | { | |
5442 | int val = INTVAL (operands[1]); | |
5443 | ||
5444 | operands[1] = GEN_INT (0xff); | |
5445 | operands[2] = GEN_INT (val - 0xff); | |
5446 | }") | |
5447 | ||
5448 | ;; On the mips16, we can split a load of a negative constant into a | |
5449 | ;; load and a neg. That's what mips_move_1word will generate anyhow. | |
5450 | ||
5451 | (define_split | |
5452 | [(set (match_operand:SI 0 "register_operand" "") | |
5453 | (match_operand:SI 1 "const_int_operand" ""))] | |
5454 | "TARGET_MIPS16 && reload_completed | |
5455 | && GET_CODE (operands[0]) == REG | |
5456 | && M16_REG_P (REGNO (operands[0])) | |
5457 | && GET_CODE (operands[1]) == CONST_INT | |
5458 | && INTVAL (operands[1]) < 0 | |
5459 | && INTVAL (operands[1]) > - 0x8000" | |
5460 | [(set (match_dup 0) (match_dup 1)) | |
5461 | (set (match_dup 0) (neg:SI (match_dup 0)))] | |
5462 | " | |
5463 | { | |
5464 | operands[1] = GEN_INT (- INTVAL (operands[1])); | |
5465 | }") | |
5466 | ||
5467 | ;; Reload HILO_REGNUM in SI mode. This needs a scratch register in | |
5468 | ;; order to set the sign bit correctly in the HI register. | |
5469 | ||
5470 | (define_expand "reload_outsi" | |
5471 | [(set (match_operand:SI 0 "general_operand" "=b") | |
5472 | (match_operand:SI 1 "register_operand" "b")) | |
5473 | (clobber (match_operand:SI 2 "register_operand" "=&d"))] | |
5474 | "TARGET_64BIT || TARGET_MIPS16" | |
5475 | " | |
5476 | { | |
5477 | if (TARGET_64BIT | |
5478 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM) | |
225b8835 | 5479 | { |
c5c76735 | 5480 | emit_insn (gen_movsi (gen_rtx_REG (SImode, 65), operands[1])); |
225b8835 ILT |
5481 | emit_insn (gen_ashrsi3 (operands[2], operands[1], GEN_INT (31))); |
5482 | emit_insn (gen_movsi (gen_rtx (REG, SImode, 64), operands[2])); | |
839366dd | 5483 | emit_insn (gen_rtx_USE (VOIDmode, operands[0])); |
225b8835 ILT |
5484 | DONE; |
5485 | } | |
2bcb2ab3 GK |
5486 | /* Use a mult to reload LO on mips16. ??? This is hideous. */ |
5487 | if (TARGET_MIPS16 | |
5488 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == LO_REGNUM) | |
5489 | { | |
5490 | emit_insn (gen_movsi (operands[2], GEN_INT (1))); | |
5491 | /* This is gen_mulsi3_internal, but we need to fill in the | |
5492 | scratch registers. */ | |
5493 | emit_insn (gen_rtx (PARALLEL, VOIDmode, | |
5494 | gen_rtvec (3, | |
5495 | gen_rtx (SET, VOIDmode, | |
5496 | operands[0], | |
5497 | gen_rtx (MULT, SImode, | |
5498 | operands[1], | |
5499 | operands[2])), | |
5500 | gen_rtx (CLOBBER, VOIDmode, | |
5501 | gen_rtx (REG, SImode, 64)), | |
5502 | gen_rtx (CLOBBER, VOIDmode, | |
5503 | gen_rtx (REG, SImode, 66))))); | |
5504 | DONE; | |
5505 | } | |
5506 | /* FIXME: I don't know how to get a value into the HI register. */ | |
ca45b913 JW |
5507 | if (GET_CODE (operands[0]) == REG |
5508 | && (TARGET_MIPS16 ? M16_REG_P (REGNO (operands[0])) | |
5509 | : GP_REG_P (REGNO (operands[0])))) | |
2bcb2ab3 GK |
5510 | { |
5511 | emit_move_insn (operands[0], operands[1]); | |
5512 | DONE; | |
5513 | } | |
225b8835 ILT |
5514 | /* This handles moves between a float register and HI/LO. */ |
5515 | emit_move_insn (operands[2], operands[1]); | |
5516 | emit_move_insn (operands[0], operands[2]); | |
5517 | DONE; | |
5518 | }") | |
0fb5ac6f | 5519 | |
2bcb2ab3 GK |
5520 | ;; Reload a value into HI or LO. There is no mthi or mtlo on mips16, |
5521 | ;; so we use a mult. ??? This is hideous, and we ought to figure out | |
5522 | ;; something better. | |
5523 | ||
bf4f78ee JW |
5524 | ;; We use no predicate for operand1, because it may be a PLUS, and there |
5525 | ;; is no convenient predicate for that. | |
5526 | ||
2bcb2ab3 GK |
5527 | (define_expand "reload_insi" |
5528 | [(set (match_operand:SI 0 "register_operand" "=b") | |
bf4f78ee | 5529 | (match_operand:SI 1 "" "b")) |
2bcb2ab3 GK |
5530 | (clobber (match_operand:SI 2 "register_operand" "=&d"))] |
5531 | "TARGET_MIPS16" | |
5532 | " | |
5533 | { | |
5534 | if (TARGET_MIPS16 | |
5535 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == LO_REGNUM) | |
5536 | { | |
5537 | emit_insn (gen_movsi (operands[2], GEN_INT (1))); | |
5538 | /* This is gen_mulsi3_internal, but we need to fill in the | |
5539 | scratch registers. */ | |
5540 | emit_insn (gen_rtx (PARALLEL, VOIDmode, | |
5541 | gen_rtvec (3, | |
5542 | gen_rtx (SET, VOIDmode, | |
5543 | operands[0], | |
5544 | gen_rtx (MULT, SImode, | |
5545 | operands[1], | |
5546 | operands[2])), | |
5547 | gen_rtx (CLOBBER, VOIDmode, | |
5548 | gen_rtx (REG, SImode, 64)), | |
5549 | gen_rtx (CLOBBER, VOIDmode, | |
5550 | gen_rtx (REG, SImode, 66))))); | |
5551 | DONE; | |
5552 | } | |
bf4f78ee JW |
5553 | |
5554 | /* If this is a plus, then this must be an add of the stack pointer against | |
5555 | either a hard register or a pseudo. */ | |
5556 | if (TARGET_MIPS16 && GET_CODE (operands[1]) == PLUS) | |
5557 | { | |
5558 | rtx plus_op; | |
5559 | ||
5560 | if (XEXP (operands[1], 0) == stack_pointer_rtx) | |
5561 | plus_op = XEXP (operands[1], 1); | |
5562 | else if (XEXP (operands[1], 1) == stack_pointer_rtx) | |
5563 | plus_op = XEXP (operands[1], 0); | |
5564 | else | |
5565 | abort (); | |
5566 | ||
5567 | /* We should have a register now. */ | |
5568 | if (GET_CODE (plus_op) != REG) | |
5569 | abort (); | |
5570 | ||
5571 | if (REGNO (plus_op) < FIRST_PSEUDO_REGISTER) | |
5572 | { | |
5573 | /* We have to have at least one temporary register which is not | |
5574 | overlapping plus_op. */ | |
5575 | if (! rtx_equal_p (plus_op, operands[0])) | |
5576 | { | |
5577 | emit_move_insn (operands[0], stack_pointer_rtx); | |
5578 | emit_insn (gen_addsi3 (operands[0], operands[0], plus_op)); | |
5579 | } | |
5580 | else if (! rtx_equal_p (plus_op, operands[2])) | |
5581 | { | |
5582 | emit_move_insn (operands[2], stack_pointer_rtx); | |
5583 | emit_insn (gen_addsi3 (operands[0], plus_op, operands[2])); | |
5584 | } | |
5585 | else | |
5586 | abort (); | |
5587 | } | |
5588 | else | |
5589 | { | |
5590 | /* We need two registers in this case. */ | |
5591 | if (! rtx_equal_p (operands[0], operands[2])) | |
5592 | { | |
5593 | emit_move_insn (operands[0], stack_pointer_rtx); | |
5594 | emit_move_insn (operands[2], plus_op); | |
5595 | emit_insn (gen_addsi3 (operands[0], operands[0], operands[2])); | |
5596 | } | |
5597 | else | |
5598 | abort (); | |
5599 | } | |
5600 | DONE; | |
5601 | } | |
5602 | ||
2bcb2ab3 GK |
5603 | /* FIXME: I don't know how to get a value into the HI register. */ |
5604 | emit_move_insn (operands[0], operands[1]); | |
5605 | DONE; | |
5606 | }") | |
5607 | ||
b8eb88d0 ILT |
5608 | ;; This insn handles moving CCmode values. It's really just a |
5609 | ;; slightly simplified copy of movsi_internal2, with additional cases | |
5610 | ;; to move a condition register to a general register and to move | |
5611 | ;; between the general registers and the floating point registers. | |
5612 | ||
5613 | (define_insn "movcc" | |
5614 | [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*d,*R,*m,*d,*f,*f,*f,*f,*R,*m") | |
5615 | (match_operand:CC 1 "general_operand" "z,*d,*R,*m,*d,*d,*f,*d,*f,*R,*m,*f,*f"))] | |
76ee8042 | 5616 | "ISA_HAS_8CC && TARGET_HARD_FLOAT" |
b8eb88d0 ILT |
5617 | "* return mips_move_1word (operands, insn, FALSE);" |
5618 | [(set_attr "type" "move,move,load,load,store,store,xfer,xfer,move,load,load,store,store") | |
5619 | (set_attr "mode" "SI") | |
0ff83799 | 5620 | (set_attr "length" "8,4,4,8,4,8,4,4,4,4,8,4,8")]) |
b8eb88d0 ILT |
5621 | |
5622 | ;; Reload condition code registers. These need scratch registers. | |
5623 | ||
5624 | (define_expand "reload_incc" | |
5625 | [(set (match_operand:CC 0 "register_operand" "=z") | |
5626 | (match_operand:CC 1 "general_operand" "z")) | |
5627 | (clobber (match_operand:TF 2 "register_operand" "=&f"))] | |
76ee8042 | 5628 | "ISA_HAS_8CC && TARGET_HARD_FLOAT" |
b8eb88d0 ILT |
5629 | " |
5630 | { | |
5631 | rtx source; | |
5632 | rtx fp1, fp2; | |
5633 | ||
5634 | /* This is called when are copying some value into a condition code | |
5635 | register. Operand 0 is the condition code register. Operand 1 | |
5636 | is the source. Operand 2 is a scratch register; we use TFmode | |
5637 | because we actually need two floating point registers. */ | |
5638 | if (! ST_REG_P (true_regnum (operands[0])) | |
5639 | || ! FP_REG_P (true_regnum (operands[2]))) | |
5640 | abort (); | |
5641 | ||
5642 | /* We need to get the source in SFmode so that the insn is | |
5643 | recognized. */ | |
5644 | if (GET_CODE (operands[1]) == MEM) | |
5645 | source = change_address (operands[1], SFmode, NULL_RTX); | |
5646 | else if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG) | |
c5c76735 | 5647 | source = gen_rtx_REG (SFmode, true_regnum (operands[1])); |
b8eb88d0 ILT |
5648 | else |
5649 | source = operands[1]; | |
5650 | ||
c5c76735 JL |
5651 | fp1 = gen_rtx_REG (SFmode, REGNO (operands[2])); |
5652 | fp2 = gen_rtx_REG (SFmode, REGNO (operands[2]) + 1); | |
b8eb88d0 ILT |
5653 | |
5654 | emit_insn (gen_move_insn (fp1, source)); | |
c5c76735 JL |
5655 | emit_insn (gen_move_insn (fp2, gen_rtx_REG (SFmode, 0))); |
5656 | emit_insn (gen_rtx_SET (VOIDmode, operands[0], | |
5657 | gen_rtx_LT (CCmode, fp2, fp1))); | |
b8eb88d0 ILT |
5658 | |
5659 | DONE; | |
5660 | }") | |
5661 | ||
5662 | (define_expand "reload_outcc" | |
5663 | [(set (match_operand:CC 0 "general_operand" "=z") | |
5664 | (match_operand:CC 1 "register_operand" "z")) | |
5665 | (clobber (match_operand:CC 2 "register_operand" "=&d"))] | |
76ee8042 | 5666 | "ISA_HAS_8CC && TARGET_HARD_FLOAT" |
b8eb88d0 ILT |
5667 | " |
5668 | { | |
5669 | /* This is called when we are copying a condition code register out | |
5670 | to save it somewhere. Operand 0 should be the location we are | |
5671 | going to save it to. Operand 1 should be the condition code | |
5672 | register. Operand 2 should be a scratch general purpose register | |
5673 | created for us by reload. The mips_secondary_reload_class | |
5674 | function should have told reload that we don't need a scratch | |
5675 | register if the destination is a general purpose register anyhow. */ | |
5676 | if (ST_REG_P (true_regnum (operands[0])) | |
5677 | || GP_REG_P (true_regnum (operands[0])) | |
5678 | || ! ST_REG_P (true_regnum (operands[1])) | |
5679 | || ! GP_REG_P (true_regnum (operands[2]))) | |
5680 | abort (); | |
5681 | ||
5682 | /* All we have to do is copy the value from the condition code to | |
5683 | the data register, which movcc can handle, and then store the | |
5684 | value into the real final destination. */ | |
5685 | emit_insn (gen_move_insn (operands[2], operands[1])); | |
5686 | emit_insn (gen_move_insn (operands[0], operands[2])); | |
5687 | ||
5688 | DONE; | |
5689 | }") | |
5690 | ||
5691 | ;; MIPS4 supports loading and storing a floating point register from | |
5692 | ;; the sum of two general registers. We use two versions for each of | |
5693 | ;; these four instructions: one where the two general registers are | |
5694 | ;; SImode, and one where they are DImode. This is because general | |
5695 | ;; registers will be in SImode when they hold 32 bit values, but, | |
5696 | ;; since the 32 bit values are always sign extended, the [ls][wd]xc1 | |
5697 | ;; instructions will still work correctly. | |
5698 | ||
5699 | ;; ??? Perhaps it would be better to support these instructions by | |
5700 | ;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since | |
5701 | ;; these instructions can only be used to load and store floating | |
5702 | ;; point registers, that would probably cause trouble in reload. | |
5703 | ||
5704 | (define_insn "" | |
5705 | [(set (match_operand:SF 0 "register_operand" "=f") | |
5706 | (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d") | |
5707 | (match_operand:SI 2 "register_operand" "d"))))] | |
1d5d552e | 5708 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT" |
b8eb88d0 ILT |
5709 | "lwxc1\\t%0,%1(%2)" |
5710 | [(set_attr "type" "load") | |
0ff83799 | 5711 | (set_attr "mode" "SF")]) |
b8eb88d0 ILT |
5712 | |
5713 | (define_insn "" | |
5714 | [(set (match_operand:SF 0 "register_operand" "=f") | |
1908a152 ILT |
5715 | (mem:SF (plus:DI (match_operand:DI 1 "se_register_operand" "d") |
5716 | (match_operand:DI 2 "se_register_operand" "d"))))] | |
1d5d552e | 5717 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT" |
b8eb88d0 ILT |
5718 | "lwxc1\\t%0,%1(%2)" |
5719 | [(set_attr "type" "load") | |
0ff83799 | 5720 | (set_attr "mode" "SF")]) |
b8eb88d0 ILT |
5721 | |
5722 | (define_insn "" | |
5723 | [(set (match_operand:DF 0 "register_operand" "=f") | |
5724 | (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d") | |
5725 | (match_operand:SI 2 "register_operand" "d"))))] | |
1d5d552e | 5726 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
b8eb88d0 ILT |
5727 | "ldxc1\\t%0,%1(%2)" |
5728 | [(set_attr "type" "load") | |
0ff83799 | 5729 | (set_attr "mode" "DF")]) |
b8eb88d0 ILT |
5730 | |
5731 | (define_insn "" | |
5732 | [(set (match_operand:DF 0 "register_operand" "=f") | |
1908a152 ILT |
5733 | (mem:DF (plus:DI (match_operand:DI 1 "se_register_operand" "d") |
5734 | (match_operand:DI 2 "se_register_operand" "d"))))] | |
1d5d552e | 5735 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
b8eb88d0 ILT |
5736 | "ldxc1\\t%0,%1(%2)" |
5737 | [(set_attr "type" "load") | |
0ff83799 | 5738 | (set_attr "mode" "DF")]) |
b8eb88d0 ILT |
5739 | |
5740 | (define_insn "" | |
5741 | [(set (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d") | |
5742 | (match_operand:SI 2 "register_operand" "d"))) | |
c5c76735 | 5743 | (match_operand:SF 0 "register_operand" "f"))] |
1d5d552e | 5744 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT" |
b8eb88d0 ILT |
5745 | "swxc1\\t%0,%1(%2)" |
5746 | [(set_attr "type" "store") | |
0ff83799 | 5747 | (set_attr "mode" "SF")]) |
b8eb88d0 ILT |
5748 | |
5749 | (define_insn "" | |
1908a152 ILT |
5750 | [(set (mem:SF (plus:DI (match_operand:DI 1 "se_register_operand" "d") |
5751 | (match_operand:DI 2 "se_register_operand" "d"))) | |
c5c76735 | 5752 | (match_operand:SF 0 "register_operand" "f"))] |
1d5d552e | 5753 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT" |
b8eb88d0 ILT |
5754 | "swxc1\\t%0,%1(%2)" |
5755 | [(set_attr "type" "store") | |
0ff83799 | 5756 | (set_attr "mode" "SF")]) |
b8eb88d0 ILT |
5757 | |
5758 | (define_insn "" | |
5759 | [(set (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d") | |
5760 | (match_operand:SI 2 "register_operand" "d"))) | |
c5c76735 | 5761 | (match_operand:DF 0 "register_operand" "f"))] |
1d5d552e | 5762 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
b8eb88d0 ILT |
5763 | "sdxc1\\t%0,%1(%2)" |
5764 | [(set_attr "type" "store") | |
0ff83799 | 5765 | (set_attr "mode" "DF")]) |
b8eb88d0 ILT |
5766 | |
5767 | (define_insn "" | |
1908a152 ILT |
5768 | [(set (mem:DF (plus:DI (match_operand:DI 1 "se_register_operand" "d") |
5769 | (match_operand:DI 2 "se_register_operand" "d"))) | |
c5c76735 | 5770 | (match_operand:DF 0 "register_operand" "f"))] |
1d5d552e | 5771 | "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
b8eb88d0 ILT |
5772 | "sdxc1\\t%0,%1(%2)" |
5773 | [(set_attr "type" "store") | |
0ff83799 | 5774 | (set_attr "mode" "DF")]) |
b8eb88d0 | 5775 | |
8ef30996 MM |
5776 | ;; 16-bit Integer moves |
5777 | ||
5778 | ;; Unlike most other insns, the move insns can't be split with | |
5779 | ;; different predicates, because register spilling and other parts of | |
5780 | ;; the compiler, have memoized the insn number already. | |
5781 | ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined | |
5782 | ||
0fb5ac6f MM |
5783 | (define_expand "movhi" |
5784 | [(set (match_operand:HI 0 "nonimmediate_operand" "") | |
5785 | (match_operand:HI 1 "general_operand" ""))] | |
8ef30996 | 5786 | "" |
ed50ab35 MM |
5787 | " |
5788 | { | |
5789 | if ((reload_in_progress | reload_completed) == 0 | |
5790 | && !register_operand (operands[0], HImode) | |
5791 | && !register_operand (operands[1], HImode) | |
2bcb2ab3 GK |
5792 | && (TARGET_MIPS16 |
5793 | || (GET_CODE (operands[1]) != CONST_INT | |
5794 | || INTVAL (operands[1]) != 0))) | |
ed50ab35 MM |
5795 | { |
5796 | rtx temp = force_reg (HImode, operands[1]); | |
5797 | emit_move_insn (operands[0], temp); | |
5798 | DONE; | |
5799 | } | |
5800 | }") | |
0fb5ac6f MM |
5801 | |
5802 | ;; The difference between these two is whether or not ints are allowed | |
5803 | ;; in FP registers (off by default, use -mdebugh to enable). | |
5804 | ||
5805 | (define_insn "movhi_internal1" | |
252e25c6 MM |
5806 | [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f*z,*x,*d") |
5807 | (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] | |
2bcb2ab3 | 5808 | "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 |
ed50ab35 MM |
5809 | && (register_operand (operands[0], HImode) |
5810 | || register_operand (operands[1], HImode) | |
5811 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" | |
8ef30996 MM |
5812 | "* return mips_move_1word (operands, insn, TRUE);" |
5813 | [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") | |
92b4cee1 | 5814 | (set_attr "mode" "HI") |
0ff83799 | 5815 | (set_attr "length" "4,4,4,8,4,8,4,4,4,4,4")]) |
8ef30996 | 5816 | |
0fb5ac6f MM |
5817 | (define_insn "movhi_internal2" |
5818 | [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") | |
5819 | (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] | |
2bcb2ab3 | 5820 | "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 |
ed50ab35 MM |
5821 | && (register_operand (operands[0], HImode) |
5822 | || register_operand (operands[1], HImode) | |
5823 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" | |
0fb5ac6f MM |
5824 | "* return mips_move_1word (operands, insn, TRUE);" |
5825 | [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") | |
5826 | (set_attr "mode" "HI") | |
0ff83799 | 5827 | (set_attr "length" "4,4,4,8,4,8,4,4,4,4")]) |
0fb5ac6f | 5828 | |
2bcb2ab3 GK |
5829 | (define_insn "" |
5830 | [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,m,*d") | |
5831 | (match_operand:HI 1 "general_operand" "d,d,y,K,N,R,m,d,d,*x"))] | |
5832 | "TARGET_MIPS16 | |
5833 | && (register_operand (operands[0], HImode) | |
5834 | || register_operand (operands[1], HImode))" | |
5835 | "* return mips_move_1word (operands, insn, TRUE);" | |
5836 | [(set_attr "type" "move,move,move,arith,arith,load,load,store,store,hilo") | |
5837 | (set_attr "mode" "HI") | |
5838 | (set_attr_alternative "length" | |
0ff83799 MM |
5839 | [(const_int 4) |
5840 | (const_int 4) | |
5841 | (const_int 4) | |
2bcb2ab3 | 5842 | (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") |
0ff83799 MM |
5843 | (const_int 4) |
5844 | (const_int 8)) | |
2bcb2ab3 | 5845 | (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") |
0ff83799 MM |
5846 | (const_int 8) |
5847 | (const_int 12)) | |
5848 | (const_int 4) | |
5849 | (const_int 8) | |
5850 | (const_int 4) | |
5851 | (const_int 8) | |
5852 | (const_int 4)])]) | |
2bcb2ab3 GK |
5853 | |
5854 | ||
5855 | ;; On the mips16, we can split lh $r,N($r) into an add and a load, | |
5856 | ;; when the original load is a 4 byte instruction but the add and the | |
5857 | ;; load are 2 2 byte instructions. | |
5858 | ||
5859 | (define_split | |
5860 | [(set (match_operand:HI 0 "register_operand" "") | |
988ee12c | 5861 | (mem:HI (plus:SI (match_dup 0) |
2bcb2ab3 GK |
5862 | (match_operand:SI 1 "const_int_operand" ""))))] |
5863 | "TARGET_MIPS16 && reload_completed | |
5864 | && GET_CODE (operands[0]) == REG | |
5865 | && M16_REG_P (REGNO (operands[0])) | |
5866 | && GET_CODE (operands[1]) == CONST_INT | |
5867 | && ((INTVAL (operands[1]) < 0 | |
5868 | && INTVAL (operands[1]) >= -0x80) | |
5869 | || (INTVAL (operands[1]) >= 32 * 2 | |
5870 | && INTVAL (operands[1]) <= 31 * 2 + 0x7e) | |
5871 | || (INTVAL (operands[1]) >= 0 | |
5872 | && INTVAL (operands[1]) < 32 * 2 | |
5873 | && (INTVAL (operands[1]) & 1) != 0))" | |
5874 | [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) | |
5875 | (set (match_dup 0) (mem:HI (plus:SI (match_dup 0) (match_dup 2))))] | |
5876 | " | |
5877 | { | |
5878 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
5879 | ||
5880 | if (val < 0) | |
5881 | operands[2] = GEN_INT (0); | |
5882 | else if (val >= 32 * 2) | |
5883 | { | |
5884 | int off = val & 1; | |
5885 | ||
5886 | operands[1] = GEN_INT (0x7e + off); | |
5887 | operands[2] = GEN_INT (val - off - 0x7e); | |
5888 | } | |
5889 | else | |
5890 | { | |
5891 | int off = val & 1; | |
5892 | ||
5893 | operands[1] = GEN_INT (off); | |
5894 | operands[2] = GEN_INT (val - off); | |
5895 | } | |
5896 | }") | |
0fb5ac6f | 5897 | |
8ef30996 MM |
5898 | ;; 8-bit Integer moves |
5899 | ||
5900 | ;; Unlike most other insns, the move insns can't be split with | |
5901 | ;; different predicates, because register spilling and other parts of | |
5902 | ;; the compiler, have memoized the insn number already. | |
5903 | ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined | |
5904 | ||
0fb5ac6f MM |
5905 | (define_expand "movqi" |
5906 | [(set (match_operand:QI 0 "nonimmediate_operand" "") | |
5907 | (match_operand:QI 1 "general_operand" ""))] | |
8ef30996 | 5908 | "" |
ed50ab35 MM |
5909 | " |
5910 | { | |
5911 | if ((reload_in_progress | reload_completed) == 0 | |
5912 | && !register_operand (operands[0], QImode) | |
5913 | && !register_operand (operands[1], QImode) | |
2bcb2ab3 GK |
5914 | && (TARGET_MIPS16 |
5915 | || (GET_CODE (operands[1]) != CONST_INT | |
5916 | || INTVAL (operands[1]) != 0))) | |
ed50ab35 MM |
5917 | { |
5918 | rtx temp = force_reg (QImode, operands[1]); | |
5919 | emit_move_insn (operands[0], temp); | |
5920 | DONE; | |
5921 | } | |
5922 | }") | |
0fb5ac6f MM |
5923 | |
5924 | ;; The difference between these two is whether or not ints are allowed | |
5925 | ;; in FP registers (off by default, use -mdebugh to enable). | |
5926 | ||
5927 | (define_insn "movqi_internal1" | |
252e25c6 MM |
5928 | [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f*z,*f,*x,*d") |
5929 | (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] | |
2bcb2ab3 | 5930 | "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 |
ed50ab35 MM |
5931 | && (register_operand (operands[0], QImode) |
5932 | || register_operand (operands[1], QImode) | |
5933 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" | |
8ef30996 MM |
5934 | "* return mips_move_1word (operands, insn, TRUE);" |
5935 | [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") | |
92b4cee1 | 5936 | (set_attr "mode" "QI") |
0ff83799 | 5937 | (set_attr "length" "4,4,4,8,4,8,4,4,4,4,4")]) |
8ef30996 | 5938 | |
0fb5ac6f MM |
5939 | (define_insn "movqi_internal2" |
5940 | [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") | |
5941 | (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] | |
2bcb2ab3 | 5942 | "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 |
ed50ab35 MM |
5943 | && (register_operand (operands[0], QImode) |
5944 | || register_operand (operands[1], QImode) | |
5945 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" | |
0fb5ac6f MM |
5946 | "* return mips_move_1word (operands, insn, TRUE);" |
5947 | [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") | |
5948 | (set_attr "mode" "QI") | |
0ff83799 | 5949 | (set_attr "length" "4,4,4,8,4,8,4,4,4,4")]) |
0fb5ac6f | 5950 | |
2bcb2ab3 GK |
5951 | (define_insn "" |
5952 | [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,m,*d") | |
5953 | (match_operand:QI 1 "general_operand" "d,d,y,K,N,R,m,d,d,*x"))] | |
5954 | "TARGET_MIPS16 | |
5955 | && (register_operand (operands[0], QImode) | |
5956 | || register_operand (operands[1], QImode))" | |
5957 | "* return mips_move_1word (operands, insn, TRUE);" | |
5958 | [(set_attr "type" "move,move,move,arith,arith,load,load,store,store,hilo") | |
5959 | (set_attr "mode" "QI") | |
5960 | (set_attr_alternative "length" | |
0ff83799 MM |
5961 | [(const_int 4) |
5962 | (const_int 4) | |
5963 | (const_int 4) | |
2bcb2ab3 | 5964 | (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") |
0ff83799 MM |
5965 | (const_int 4) |
5966 | (const_int 8)) | |
2bcb2ab3 | 5967 | (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") |
0ff83799 MM |
5968 | (const_int 8) |
5969 | (const_int 12)) | |
5970 | (const_int 4) | |
5971 | (const_int 8) | |
5972 | (const_int 4) | |
5973 | (const_int 8) | |
5974 | (const_int 4)])]) | |
2bcb2ab3 GK |
5975 | |
5976 | ||
5977 | ;; On the mips16, we can split lb $r,N($r) into an add and a load, | |
5978 | ;; when the original load is a 4 byte instruction but the add and the | |
5979 | ;; load are 2 2 byte instructions. | |
5980 | ||
5981 | (define_split | |
5982 | [(set (match_operand:QI 0 "register_operand" "") | |
5983 | (mem:QI (plus:SI (match_dup 0) | |
5984 | (match_operand:SI 1 "const_int_operand" ""))))] | |
5985 | "TARGET_MIPS16 && reload_completed | |
5986 | && GET_CODE (operands[0]) == REG | |
5987 | && M16_REG_P (REGNO (operands[0])) | |
5988 | && GET_CODE (operands[1]) == CONST_INT | |
5989 | && ((INTVAL (operands[1]) < 0 | |
5990 | && INTVAL (operands[1]) >= -0x80) | |
5991 | || (INTVAL (operands[1]) >= 32 | |
5992 | && INTVAL (operands[1]) <= 31 + 0x7f))" | |
5993 | [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) | |
5994 | (set (match_dup 0) (mem:QI (plus:SI (match_dup 0) (match_dup 2))))] | |
5995 | " | |
5996 | { | |
5997 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
5998 | ||
5999 | if (val < 0) | |
6000 | operands[2] = GEN_INT (0); | |
6001 | else | |
6002 | { | |
6003 | operands[1] = GEN_INT (0x7f); | |
6004 | operands[2] = GEN_INT (val - 0x7f); | |
6005 | } | |
6006 | }") | |
8ef30996 MM |
6007 | |
6008 | ;; 32-bit floating point moves | |
6009 | ||
ed50ab35 MM |
6010 | (define_expand "movsf" |
6011 | [(set (match_operand:SF 0 "nonimmediate_operand" "") | |
6012 | (match_operand:SF 1 "general_operand" ""))] | |
6013 | "" | |
6014 | " | |
6015 | { | |
6016 | if ((reload_in_progress | reload_completed) == 0 | |
6017 | && !register_operand (operands[0], SFmode) | |
6018 | && !register_operand (operands[1], SFmode) | |
2bcb2ab3 | 6019 | && (TARGET_MIPS16 |
6e92f4b6 KG |
6020 | || ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) |
6021 | && operands[1] != CONST0_RTX (SFmode)))) | |
ed50ab35 MM |
6022 | { |
6023 | rtx temp = force_reg (SFmode, operands[1]); | |
6024 | emit_move_insn (operands[0], temp); | |
6025 | DONE; | |
6026 | } | |
6027 | }") | |
6028 | ||
b0193a92 | 6029 | (define_insn "movsf_internal1" |
8ef30996 | 6030 | [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,f,R,m,*f,*d,*d,*d,*d,*R,*m") |
bb621ad7 | 6031 | (match_operand:SF 1 "general_operand" "f,G,R,Fm,fG,fG,*d,*f,*G*d,*R,*F*m,*d,*d"))] |
b0193a92 MM |
6032 | "TARGET_HARD_FLOAT |
6033 | && (register_operand (operands[0], SFmode) | |
6034 | || register_operand (operands[1], SFmode) | |
6035 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) | |
6036 | || operands[1] == CONST0_RTX (SFmode))" | |
8ef30996 MM |
6037 | "* return mips_move_1word (operands, insn, FALSE);" |
6038 | [(set_attr "type" "move,xfer,load,load,store,store,xfer,xfer,move,load,load,store,store") | |
92b4cee1 | 6039 | (set_attr "mode" "SF") |
0ff83799 | 6040 | (set_attr "length" "4,4,4,8,4,8,4,4,4,4,8,4,8")]) |
8ef30996 | 6041 | |
ed50ab35 | 6042 | |
b0193a92 MM |
6043 | (define_insn "movsf_internal2" |
6044 | [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,R,m") | |
bb621ad7 | 6045 | (match_operand:SF 1 "general_operand" " Gd,R,Fm,d,d"))] |
2bcb2ab3 | 6046 | "TARGET_SOFT_FLOAT && !TARGET_MIPS16 |
b0193a92 MM |
6047 | && (register_operand (operands[0], SFmode) |
6048 | || register_operand (operands[1], SFmode) | |
6049 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) | |
6050 | || operands[1] == CONST0_RTX (SFmode))" | |
6051 | "* return mips_move_1word (operands, insn, FALSE);" | |
6052 | [(set_attr "type" "move,load,load,store,store") | |
6053 | (set_attr "mode" "SF") | |
0ff83799 | 6054 | (set_attr "length" "4,4,8,4,8")]) |
b0193a92 | 6055 | |
2bcb2ab3 GK |
6056 | (define_insn "" |
6057 | [(set (match_operand:SF 0 "nonimmediate_operand" "=d,y,d,d,d,R,m") | |
6058 | (match_operand:SF 1 "general_operand" "d,d,y,R,Fm,d,d"))] | |
6059 | "TARGET_MIPS16 | |
6060 | && (register_operand (operands[0], SFmode) | |
6061 | || register_operand (operands[1], SFmode))" | |
6062 | "* return mips_move_1word (operands, insn, FALSE);" | |
6063 | [(set_attr "type" "move,move,move,load,load,store,store") | |
6064 | (set_attr "mode" "SF") | |
0ff83799 | 6065 | (set_attr "length" "4,4,4,4,8,4,8")]) |
2bcb2ab3 | 6066 | |
b0193a92 | 6067 | |
8ef30996 MM |
6068 | ;; 64-bit floating point moves |
6069 | ||
ed50ab35 MM |
6070 | (define_expand "movdf" |
6071 | [(set (match_operand:DF 0 "nonimmediate_operand" "") | |
6072 | (match_operand:DF 1 "general_operand" ""))] | |
6073 | "" | |
6074 | " | |
6075 | { | |
6076 | if ((reload_in_progress | reload_completed) == 0 | |
6077 | && !register_operand (operands[0], DFmode) | |
6078 | && !register_operand (operands[1], DFmode) | |
2bcb2ab3 | 6079 | && (TARGET_MIPS16 |
6e92f4b6 KG |
6080 | || ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) |
6081 | && operands[1] != CONST0_RTX (DFmode)))) | |
ed50ab35 MM |
6082 | { |
6083 | rtx temp = force_reg (DFmode, operands[1]); | |
6084 | emit_move_insn (operands[0], temp); | |
6085 | DONE; | |
6086 | } | |
6087 | }") | |
6088 | ||
b0193a92 | 6089 | (define_insn "movdf_internal1" |
2bcb2ab3 GK |
6090 | [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,To,f,*f,*d,*d,*d,*d,*R,*T") |
6091 | (match_operand:DF 1 "general_operand" "f,R,To,fG,fG,F,*d,*f,*d*G,*R,*T*F,*d,*d"))] | |
64d8baf9 | 6092 | "TARGET_HARD_FLOAT && !(TARGET_FLOAT64 && !TARGET_64BIT) |
46299de9 | 6093 | && TARGET_DOUBLE_FLOAT |
b0193a92 MM |
6094 | && (register_operand (operands[0], DFmode) |
6095 | || register_operand (operands[1], DFmode) | |
6096 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) | |
6097 | || operands[1] == CONST0_RTX (DFmode))" | |
8ef30996 MM |
6098 | "* return mips_move_2words (operands, insn); " |
6099 | [(set_attr "type" "move,load,load,store,store,load,xfer,xfer,move,load,load,store,store") | |
92b4cee1 | 6100 | (set_attr "mode" "DF") |
0ff83799 | 6101 | (set_attr "length" "4,8,16,8,16,16,8,8,8,8,16,8,16")]) |
8ef30996 | 6102 | |
64d8baf9 | 6103 | (define_insn "movdf_internal1a" |
fc5b7cda AH |
6104 | [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,R,R,To,To,*d,*d,*d,*To,*R,*d") |
6105 | (match_operand:DF 1 "general_operand" " f,To,f,G,f,G,*F,*To,*R,*d,*d,*d"))] | |
64d8baf9 | 6106 | "TARGET_HARD_FLOAT && (TARGET_FLOAT64 && !TARGET_64BIT) |
46299de9 | 6107 | && TARGET_DOUBLE_FLOAT |
64d8baf9 | 6108 | && (register_operand (operands[0], DFmode) |
89a5e42b | 6109 | || register_operand (operands[1], DFmode) |
64d8baf9 JW |
6110 | || (GET_CODE (operands [0]) == MEM |
6111 | && ((GET_CODE (operands[1]) == CONST_INT | |
6112 | && INTVAL (operands[1]) == 0) | |
89a5e42b | 6113 | || operands[1] == CONST0_RTX (DFmode))))" |
64d8baf9 | 6114 | "* return mips_move_2words (operands, insn); " |
fc5b7cda | 6115 | [(set_attr "type" "move,load,store,store,store,store,load,load,load,store,store,move") |
64d8baf9 | 6116 | (set_attr "mode" "DF") |
fc5b7cda | 6117 | (set_attr "length" "4,8,4,4,8,8,8,8,4,8,4,4")]) |
64d8baf9 | 6118 | |
b0193a92 | 6119 | (define_insn "movdf_internal2" |
2bcb2ab3 GK |
6120 | [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,R,To") |
6121 | (match_operand:DF 1 "general_operand" "dG,R,ToF,d,d"))] | |
6122 | "(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16 | |
b0193a92 MM |
6123 | && (register_operand (operands[0], DFmode) |
6124 | || register_operand (operands[1], DFmode) | |
6125 | || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) | |
6126 | || operands[1] == CONST0_RTX (DFmode))" | |
6127 | "* return mips_move_2words (operands, insn); " | |
6128 | [(set_attr "type" "move,load,load,store,store") | |
6129 | (set_attr "mode" "DF") | |
0ff83799 | 6130 | (set_attr "length" "8,8,16,8,16")]) |
b0193a92 | 6131 | |
2bcb2ab3 GK |
6132 | (define_insn "" |
6133 | [(set (match_operand:DF 0 "nonimmediate_operand" "=d,y,d,d,d,R,To") | |
6134 | (match_operand:DF 1 "general_operand" "d,d,y,R,ToF,d,d"))] | |
6135 | "TARGET_MIPS16 | |
6136 | && (register_operand (operands[0], DFmode) | |
6137 | || register_operand (operands[1], DFmode))" | |
6138 | "* return mips_move_2words (operands, insn);" | |
6139 | [(set_attr "type" "move,move,move,load,load,store,store") | |
6140 | (set_attr "mode" "DF") | |
0ff83799 | 6141 | (set_attr "length" "8,8,8,8,16,8,16")]) |
2bcb2ab3 | 6142 | |
8ef30996 MM |
6143 | (define_split |
6144 | [(set (match_operand:DF 0 "register_operand" "") | |
6145 | (match_operand:DF 1 "register_operand" ""))] | |
2c14c928 | 6146 | "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
8ef30996 MM |
6147 | && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) |
6148 | && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" | |
8ef30996 | 6149 | [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) |
ddef6bc7 | 6150 | (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))] |
8ef30996 MM |
6151 | "") |
6152 | ||
e19ff60f JW |
6153 | ;; Instructions to load the global pointer register. |
6154 | ;; This is volatile to make sure that the scheduler won't move any symbol_ref | |
6155 | ;; uses in front of it. All symbol_refs implicitly use the gp reg. | |
6156 | ||
6157 | (define_insn "loadgp" | |
6158 | [(set (reg:DI 28) | |
e5e809f4 JL |
6159 | (unspec_volatile:DI [(match_operand:DI 0 "address_operand" "") |
6160 | (match_operand:DI 1 "register_operand" "")] 2)) | |
e19ff60f JW |
6161 | (clobber (reg:DI 1))] |
6162 | "" | |
e5e809f4 | 6163 | "%[lui\\t$1,%%hi(%%neg(%%gp_rel(%a0)))\\n\\taddiu\\t$1,$1,%%lo(%%neg(%%gp_rel(%a0)))\\n\\tdaddu\\t$gp,$1,%1%]" |
e19ff60f JW |
6164 | [(set_attr "type" "move") |
6165 | (set_attr "mode" "DI") | |
0ff83799 | 6166 | (set_attr "length" "12")]) |
26b8e6e5 | 6167 | \f |
8ef30996 MM |
6168 | ;; Block moves, see mips.c for more details. |
6169 | ;; Argument 0 is the destination | |
6170 | ;; Argument 1 is the source | |
6171 | ;; Argument 2 is the length | |
6172 | ;; Argument 3 is the alignment | |
6173 | ||
6174 | (define_expand "movstrsi" | |
e9a25f70 JL |
6175 | [(parallel [(set (match_operand:BLK 0 "general_operand" "") |
6176 | (match_operand:BLK 1 "general_operand" "")) | |
8ef30996 MM |
6177 | (use (match_operand:SI 2 "arith32_operand" "")) |
6178 | (use (match_operand:SI 3 "immediate_operand" ""))])] | |
2bcb2ab3 | 6179 | "!TARGET_MIPS16" |
8ef30996 MM |
6180 | " |
6181 | { | |
6182 | if (operands[0]) /* avoid unused code messages */ | |
6183 | { | |
6184 | expand_block_move (operands); | |
6185 | DONE; | |
6186 | } | |
6187 | }") | |
6188 | ||
842eb20e MM |
6189 | ;; Insn generated by block moves |
6190 | ||
6191 | (define_insn "movstrsi_internal" | |
aa4e54c4 JW |
6192 | [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination |
6193 | (match_operand:BLK 1 "memory_operand" "o")) ;; source | |
26b8e6e5 MM |
6194 | (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 |
6195 | (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 | |
6196 | (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 | |
6197 | (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 | |
6198 | (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move | |
6199 | (use (match_operand:SI 3 "small_int" "I")) ;; alignment | |
6200 | (use (const_int 0))] ;; normal block move | |
6201 | "" | |
6202 | "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);" | |
e9a25f70 | 6203 | [(set_attr "type" "store") |
842eb20e | 6204 | (set_attr "mode" "none") |
0ff83799 | 6205 | (set_attr "length" "80")]) |
842eb20e | 6206 | |
2bcb2ab3 GK |
6207 | ;; We need mips16 versions, because an offset from the stack pointer |
6208 | ;; is not offsettable, since the stack pointer can only handle 4 and 8 | |
6209 | ;; byte loads. | |
6210 | ||
2bcb2ab3 GK |
6211 | (define_insn "" |
6212 | [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination | |
cf45bb06 | 6213 | (match_operand:BLK 1 "memory_operand" "o")) ;; source |
2bcb2ab3 GK |
6214 | (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 |
6215 | (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 | |
6216 | (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 | |
6217 | (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 | |
6218 | (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move | |
6219 | (use (match_operand:SI 3 "small_int" "I")) ;; alignment | |
6220 | (use (const_int 0))] ;; normal block move | |
6221 | "TARGET_MIPS16" | |
6222 | "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);" | |
6223 | [(set_attr "type" "multi") | |
6224 | (set_attr "mode" "none") | |
0ff83799 | 6225 | (set_attr "length" "80")]) |
2bcb2ab3 | 6226 | |
26b8e6e5 MM |
6227 | ;; Split a block move into 2 parts, the first part is everything |
6228 | ;; except for the last move, and the second part is just the last | |
6229 | ;; store, which is exactly 1 instruction (ie, not a usw), so it can | |
6230 | ;; fill a delay slot. This also prevents a bug in delayed branches | |
6231 | ;; from showing up, which reuses one of the registers in our clobbers. | |
6232 | ||
6233 | (define_split | |
6234 | [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) | |
6235 | (mem:BLK (match_operand:SI 1 "register_operand" ""))) | |
6236 | (clobber (match_operand:SI 4 "register_operand" "")) | |
6237 | (clobber (match_operand:SI 5 "register_operand" "")) | |
6238 | (clobber (match_operand:SI 6 "register_operand" "")) | |
6239 | (clobber (match_operand:SI 7 "register_operand" "")) | |
6240 | (use (match_operand:SI 2 "small_int" "")) | |
6241 | (use (match_operand:SI 3 "small_int" "")) | |
6242 | (use (const_int 0))] | |
6243 | ||
6244 | "reload_completed && !TARGET_DEBUG_D_MODE && INTVAL (operands[2]) > 0" | |
6245 | ||
6246 | ;; All but the last move | |
6247 | [(parallel [(set (mem:BLK (match_dup 0)) | |
6248 | (mem:BLK (match_dup 1))) | |
6249 | (clobber (match_dup 4)) | |
6250 | (clobber (match_dup 5)) | |
6251 | (clobber (match_dup 6)) | |
6252 | (clobber (match_dup 7)) | |
6253 | (use (match_dup 2)) | |
6254 | (use (match_dup 3)) | |
6255 | (use (const_int 1))]) | |
6256 | ||
6257 | ;; The last store, so it can fill a delay slot | |
6258 | (parallel [(set (mem:BLK (match_dup 0)) | |
6259 | (mem:BLK (match_dup 1))) | |
6260 | (clobber (match_dup 4)) | |
6261 | (clobber (match_dup 5)) | |
6262 | (clobber (match_dup 6)) | |
6263 | (clobber (match_dup 7)) | |
6264 | (use (match_dup 2)) | |
6265 | (use (match_dup 3)) | |
6266 | (use (const_int 2))])] | |
6267 | ||
6268 | "") | |
6269 | ||
6270 | (define_insn "movstrsi_internal2" | |
aa4e54c4 JW |
6271 | [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination |
6272 | (match_operand:BLK 1 "memory_operand" "o")) ;; source | |
26b8e6e5 MM |
6273 | (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 |
6274 | (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 | |
6275 | (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 | |
6276 | (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 | |
6277 | (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move | |
6278 | (use (match_operand:SI 3 "small_int" "I")) ;; alignment | |
6279 | (use (const_int 1))] ;; all but last store | |
6280 | "" | |
6281 | "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NOT_LAST);" | |
e9a25f70 | 6282 | [(set_attr "type" "store") |
26b8e6e5 | 6283 | (set_attr "mode" "none") |
0ff83799 | 6284 | (set_attr "length" "80")]) |
26b8e6e5 | 6285 | |
2bcb2ab3 | 6286 | (define_insn "" |
cf45bb06 RH |
6287 | [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination |
6288 | (match_operand:BLK 1 "memory_operand" "o")) ;; source | |
2bcb2ab3 GK |
6289 | (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 |
6290 | (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 | |
6291 | (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 | |
6292 | (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 | |
6293 | (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move | |
6294 | (use (match_operand:SI 3 "small_int" "I")) ;; alignment | |
6295 | (use (const_int 1))] ;; all but last store | |
6296 | "TARGET_MIPS16" | |
6297 | "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NOT_LAST);" | |
6298 | [(set_attr "type" "multi") | |
6299 | (set_attr "mode" "none") | |
0ff83799 | 6300 | (set_attr "length" "80")]) |
2bcb2ab3 | 6301 | |
26b8e6e5 MM |
6302 | (define_insn "movstrsi_internal3" |
6303 | [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination | |
6304 | (match_operand:BLK 1 "memory_operand" "Ro")) ;; source | |
6305 | (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 | |
6306 | (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 | |
6307 | (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 | |
6308 | (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 | |
6309 | (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move | |
6310 | (use (match_operand:SI 3 "small_int" "I")) ;; alignment | |
bb621ad7 | 6311 | (use (const_int 2))] ;; just last store of block move |
26b8e6e5 MM |
6312 | "" |
6313 | "* return output_block_move (insn, operands, 4, BLOCK_MOVE_LAST);" | |
6314 | [(set_attr "type" "store") | |
0ff83799 | 6315 | (set_attr "mode" "none")]) |
8ef30996 MM |
6316 | \f |
6317 | ;; | |
6318 | ;; .................... | |
6319 | ;; | |
6320 | ;; SHIFTS | |
6321 | ;; | |
6322 | ;; .................... | |
6323 | ||
2bcb2ab3 GK |
6324 | ;; Many of these instructions uses trivial define_expands, because we |
6325 | ;; want to use a different set of constraints when TARGET_MIPS16. | |
6326 | ||
6327 | (define_expand "ashlsi3" | |
8ef30996 MM |
6328 | [(set (match_operand:SI 0 "register_operand" "=d") |
6329 | (ashift:SI (match_operand:SI 1 "register_operand" "d") | |
6330 | (match_operand:SI 2 "arith_operand" "dI")))] | |
6331 | "" | |
2bcb2ab3 GK |
6332 | " |
6333 | { | |
6334 | /* On the mips16, a shift of more than 8 is a four byte instruction, | |
6335 | so, for a shift between 8 and 16, it is just as fast to do two | |
6336 | shifts of 8 or less. If there is a lot of shifting going on, we | |
6337 | may win in CSE. Otherwise combine will put the shifts back | |
6338 | together again. This can be called by function_arg, so we must | |
6339 | be careful not to allocate a new register if we've reached the | |
6340 | reload pass. */ | |
6341 | if (TARGET_MIPS16 | |
6342 | && optimize | |
6343 | && GET_CODE (operands[2]) == CONST_INT | |
6344 | && INTVAL (operands[2]) > 8 | |
6345 | && INTVAL (operands[2]) <= 16 | |
6346 | && ! reload_in_progress | |
6347 | && ! reload_completed) | |
6348 | { | |
6349 | rtx temp = gen_reg_rtx (SImode); | |
6350 | ||
6351 | emit_insn (gen_ashlsi3_internal2 (temp, operands[1], GEN_INT (8))); | |
6352 | emit_insn (gen_ashlsi3_internal2 (operands[0], temp, | |
6353 | GEN_INT (INTVAL (operands[2]) - 8))); | |
6354 | DONE; | |
6355 | } | |
6356 | }") | |
6357 | ||
6358 | (define_insn "ashlsi3_internal1" | |
6359 | [(set (match_operand:SI 0 "register_operand" "=d") | |
6360 | (ashift:SI (match_operand:SI 1 "register_operand" "d") | |
6361 | (match_operand:SI 2 "arith_operand" "dI")))] | |
6362 | "!TARGET_MIPS16" | |
8ef30996 MM |
6363 | "* |
6364 | { | |
6365 | if (GET_CODE (operands[2]) == CONST_INT) | |
95936d18 | 6366 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
8ef30996 MM |
6367 | |
6368 | return \"sll\\t%0,%1,%2\"; | |
6369 | }" | |
6370 | [(set_attr "type" "arith") | |
0ff83799 | 6371 | (set_attr "mode" "SI")]) |
8ef30996 | 6372 | |
2bcb2ab3 GK |
6373 | (define_insn "ashlsi3_internal2" |
6374 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
6375 | (ashift:SI (match_operand:SI 1 "register_operand" "0,d") | |
6376 | (match_operand:SI 2 "arith_operand" "d,I")))] | |
6377 | "TARGET_MIPS16" | |
6378 | "* | |
6379 | { | |
6380 | if (which_alternative == 0) | |
6381 | return \"sll\\t%0,%2\"; | |
6382 | ||
6383 | if (GET_CODE (operands[2]) == CONST_INT) | |
95936d18 | 6384 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
2bcb2ab3 GK |
6385 | |
6386 | return \"sll\\t%0,%1,%2\"; | |
6387 | }" | |
6388 | [(set_attr "type" "arith") | |
6389 | (set_attr "mode" "SI") | |
6390 | (set_attr_alternative "length" | |
0ff83799 | 6391 | [(const_int 4) |
2bcb2ab3 | 6392 | (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") |
0ff83799 MM |
6393 | (const_int 4) |
6394 | (const_int 8))])]) | |
2bcb2ab3 GK |
6395 | |
6396 | ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. | |
6397 | ||
6398 | (define_split | |
6399 | [(set (match_operand:SI 0 "register_operand" "") | |
6400 | (ashift:SI (match_operand:SI 1 "register_operand" "") | |
6401 | (match_operand:SI 2 "const_int_operand" "")))] | |
6402 | "TARGET_MIPS16 | |
6403 | && reload_completed | |
6404 | && GET_CODE (operands[2]) == CONST_INT | |
6405 | && INTVAL (operands[2]) > 8 | |
6406 | && INTVAL (operands[2]) <= 16" | |
6407 | [(set (match_dup 0) (ashift:SI (match_dup 1) (const_int 8))) | |
6408 | (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))] | |
6409 | " | |
6410 | { | |
6411 | operands[2] = GEN_INT (INTVAL (operands[2]) - 8); | |
6412 | }") | |
8ef30996 MM |
6413 | |
6414 | (define_expand "ashldi3" | |
6415 | [(parallel [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 | 6416 | (ashift:DI (match_operand:DI 1 "se_register_operand" "") |
8ef30996 MM |
6417 | (match_operand:SI 2 "arith_operand" ""))) |
6418 | (clobber (match_dup 3))])] | |
2bcb2ab3 | 6419 | "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" |
bb621ad7 JW |
6420 | " |
6421 | { | |
6422 | if (TARGET_64BIT) | |
6423 | { | |
2bcb2ab3 GK |
6424 | /* On the mips16, a shift of more than 8 is a four byte |
6425 | instruction, so, for a shift between 8 and 16, it is just as | |
6426 | fast to do two shifts of 8 or less. If there is a lot of | |
6427 | shifting going on, we may win in CSE. Otherwise combine will | |
6428 | put the shifts back together again. This can be called by | |
6429 | function_arg, so we must be careful not to allocate a new | |
6430 | register if we've reached the reload pass. */ | |
6431 | if (TARGET_MIPS16 | |
6432 | && optimize | |
6433 | && GET_CODE (operands[2]) == CONST_INT | |
6434 | && INTVAL (operands[2]) > 8 | |
6435 | && INTVAL (operands[2]) <= 16 | |
6436 | && ! reload_in_progress | |
6437 | && ! reload_completed) | |
6438 | { | |
6439 | rtx temp = gen_reg_rtx (DImode); | |
6440 | ||
6441 | emit_insn (gen_ashldi3_internal4 (temp, operands[1], GEN_INT (8))); | |
6442 | emit_insn (gen_ashldi3_internal4 (operands[0], temp, | |
6443 | GEN_INT (INTVAL (operands[2]) - 8))); | |
6444 | DONE; | |
6445 | } | |
6446 | ||
bb621ad7 JW |
6447 | emit_insn (gen_ashldi3_internal4 (operands[0], operands[1], |
6448 | operands[2])); | |
6449 | DONE; | |
6450 | } | |
6451 | ||
6452 | operands[3] = gen_reg_rtx (SImode); | |
6453 | }") | |
8ef30996 MM |
6454 | |
6455 | ||
6456 | (define_insn "ashldi3_internal" | |
0fb5ac6f | 6457 | [(set (match_operand:DI 0 "register_operand" "=&d") |
8ef30996 MM |
6458 | (ashift:DI (match_operand:DI 1 "register_operand" "d") |
6459 | (match_operand:SI 2 "register_operand" "d"))) | |
6460 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 | 6461 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" |
8ef30996 MM |
6462 | "* |
6463 | { | |
6464 | operands[4] = const0_rtx; | |
6465 | dslots_jump_total += 3; | |
6466 | dslots_jump_filled += 2; | |
6467 | ||
6468 | return \"sll\\t%3,%2,26\\n\\ | |
6469 | \\tbgez\\t%3,1f\\n\\ | |
6470 | \\tsll\\t%M0,%L1,%2\\n\\ | |
6471 | \\t%(b\\t3f\\n\\ | |
6472 | \\tmove\\t%L0,%z4%)\\n\\ | |
6473 | \\n\\ | |
efa3896a | 6474 | %~1:\\n\\ |
8ef30996 MM |
6475 | \\t%(beq\\t%3,%z4,2f\\n\\ |
6476 | \\tsll\\t%M0,%M1,%2%)\\n\\ | |
6477 | \\n\\ | |
6478 | \\tsubu\\t%3,%z4,%2\\n\\ | |
6479 | \\tsrl\\t%3,%L1,%3\\n\\ | |
6480 | \\tor\\t%M0,%M0,%3\\n\\ | |
efa3896a | 6481 | %~2:\\n\\ |
8ef30996 | 6482 | \\tsll\\t%L0,%L1,%2\\n\\ |
efa3896a | 6483 | %~3:\"; |
8ef30996 MM |
6484 | }" |
6485 | [(set_attr "type" "darith") | |
6486 | (set_attr "mode" "SI") | |
0ff83799 | 6487 | (set_attr "length" "48")]) |
8ef30996 MM |
6488 | |
6489 | ||
6490 | (define_insn "ashldi3_internal2" | |
6491 | [(set (match_operand:DI 0 "register_operand" "=d") | |
6492 | (ashift:DI (match_operand:DI 1 "register_operand" "d") | |
6493 | (match_operand:SI 2 "small_int" "IJK"))) | |
6494 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 GK |
6495 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 |
6496 | && (INTVAL (operands[2]) & 32) != 0" | |
8ef30996 MM |
6497 | "* |
6498 | { | |
95936d18 | 6499 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
8ef30996 MM |
6500 | operands[4] = const0_rtx; |
6501 | return \"sll\\t%M0,%L1,%2\;move\\t%L0,%z4\"; | |
6502 | }" | |
6503 | [(set_attr "type" "darith") | |
6504 | (set_attr "mode" "DI") | |
0ff83799 | 6505 | (set_attr "length" "8")]) |
8ef30996 MM |
6506 | |
6507 | ||
6508 | (define_split | |
6509 | [(set (match_operand:DI 0 "register_operand" "") | |
6510 | (ashift:DI (match_operand:DI 1 "register_operand" "") | |
6511 | (match_operand:SI 2 "small_int" ""))) | |
6512 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
6513 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
6514 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
6515 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
6516 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
6517 | && (INTVAL (operands[2]) & 32) != 0" | |
6518 | ||
ddef6bc7 | 6519 | [(set (subreg:SI (match_dup 0) 4) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) |
8ef30996 MM |
6520 | (set (subreg:SI (match_dup 0) 0) (const_int 0))] |
6521 | ||
95936d18 | 6522 | "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") |
8ef30996 MM |
6523 | |
6524 | ||
6525 | (define_split | |
6526 | [(set (match_operand:DI 0 "register_operand" "") | |
6527 | (ashift:DI (match_operand:DI 1 "register_operand" "") | |
6528 | (match_operand:SI 2 "small_int" ""))) | |
6529 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
6530 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
6531 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
6532 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
6533 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
6534 | && (INTVAL (operands[2]) & 32) != 0" | |
6535 | ||
ddef6bc7 JJ |
6536 | [(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 4) (match_dup 2))) |
6537 | (set (subreg:SI (match_dup 0) 4) (const_int 0))] | |
8ef30996 | 6538 | |
95936d18 | 6539 | "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") |
8ef30996 MM |
6540 | |
6541 | ||
6542 | (define_insn "ashldi3_internal3" | |
6543 | [(set (match_operand:DI 0 "register_operand" "=d") | |
6544 | (ashift:DI (match_operand:DI 1 "register_operand" "d") | |
6545 | (match_operand:SI 2 "small_int" "IJK"))) | |
6546 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 | 6547 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 |
8ef30996 MM |
6548 | && (INTVAL (operands[2]) & 63) < 32 |
6549 | && (INTVAL (operands[2]) & 63) != 0" | |
6550 | "* | |
6551 | { | |
6552 | int amount = INTVAL (operands[2]); | |
6553 | ||
c5c76735 | 6554 | operands[2] = GEN_INT (amount & 31); |
8ef30996 | 6555 | operands[4] = const0_rtx; |
c5c76735 | 6556 | operands[5] = GEN_INT ((-amount) & 31); |
8ef30996 MM |
6557 | |
6558 | return \"sll\\t%M0,%M1,%2\;srl\\t%3,%L1,%5\;or\\t%M0,%M0,%3\;sll\\t%L0,%L1,%2\"; | |
6559 | }" | |
6560 | [(set_attr "type" "darith") | |
6561 | (set_attr "mode" "DI") | |
0ff83799 | 6562 | (set_attr "length" "16")]) |
8ef30996 MM |
6563 | |
6564 | ||
6565 | (define_split | |
6566 | [(set (match_operand:DI 0 "register_operand" "") | |
6567 | (ashift:DI (match_operand:DI 1 "register_operand" "") | |
6568 | (match_operand:SI 2 "small_int" ""))) | |
6569 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
6570 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
6571 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
6572 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
6573 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
6574 | && (INTVAL (operands[2]) & 63) < 32 | |
6575 | && (INTVAL (operands[2]) & 63) != 0" | |
6576 | ||
ddef6bc7 JJ |
6577 | [(set (subreg:SI (match_dup 0) 4) |
6578 | (ashift:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
6579 | (match_dup 2))) |
6580 | ||
6581 | (set (match_dup 3) | |
6582 | (lshiftrt:SI (subreg:SI (match_dup 1) 0) | |
6583 | (match_dup 4))) | |
6584 | ||
ddef6bc7 JJ |
6585 | (set (subreg:SI (match_dup 0) 4) |
6586 | (ior:SI (subreg:SI (match_dup 0) 4) | |
8ef30996 MM |
6587 | (match_dup 3))) |
6588 | ||
6589 | (set (subreg:SI (match_dup 0) 0) | |
6590 | (ashift:SI (subreg:SI (match_dup 1) 0) | |
6591 | (match_dup 2)))] | |
6592 | " | |
6593 | { | |
6594 | int amount = INTVAL (operands[2]); | |
c5c76735 JL |
6595 | operands[2] = GEN_INT (amount & 31); |
6596 | operands[4] = GEN_INT ((-amount) & 31); | |
8ef30996 MM |
6597 | }") |
6598 | ||
6599 | ||
6600 | (define_split | |
6601 | [(set (match_operand:DI 0 "register_operand" "") | |
6602 | (ashift:DI (match_operand:DI 1 "register_operand" "") | |
6603 | (match_operand:SI 2 "small_int" ""))) | |
6604 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
6605 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
6606 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
6607 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
6608 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
6609 | && (INTVAL (operands[2]) & 63) < 32 | |
6610 | && (INTVAL (operands[2]) & 63) != 0" | |
6611 | ||
6612 | [(set (subreg:SI (match_dup 0) 0) | |
6613 | (ashift:SI (subreg:SI (match_dup 1) 0) | |
6614 | (match_dup 2))) | |
6615 | ||
6616 | (set (match_dup 3) | |
ddef6bc7 | 6617 | (lshiftrt:SI (subreg:SI (match_dup 1) 4) |
8ef30996 MM |
6618 | (match_dup 4))) |
6619 | ||
6620 | (set (subreg:SI (match_dup 0) 0) | |
6621 | (ior:SI (subreg:SI (match_dup 0) 0) | |
6622 | (match_dup 3))) | |
6623 | ||
ddef6bc7 JJ |
6624 | (set (subreg:SI (match_dup 0) 4) |
6625 | (ashift:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
6626 | (match_dup 2)))] |
6627 | " | |
6628 | { | |
6629 | int amount = INTVAL (operands[2]); | |
c5c76735 JL |
6630 | operands[2] = GEN_INT (amount & 31); |
6631 | operands[4] = GEN_INT ((-amount) & 31); | |
8ef30996 MM |
6632 | }") |
6633 | ||
6634 | ||
bb621ad7 JW |
6635 | (define_insn "ashldi3_internal4" |
6636 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 6637 | (ashift:DI (match_operand:DI 1 "se_register_operand" "d") |
bb621ad7 | 6638 | (match_operand:SI 2 "arith_operand" "dI")))] |
2bcb2ab3 | 6639 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
6640 | "* |
6641 | { | |
6642 | if (GET_CODE (operands[2]) == CONST_INT) | |
6643 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
6644 | ||
6645 | return \"dsll\\t%0,%1,%2\"; | |
6646 | }" | |
6647 | [(set_attr "type" "arith") | |
0ff83799 | 6648 | (set_attr "mode" "DI")]) |
bb621ad7 | 6649 | |
2bcb2ab3 GK |
6650 | (define_insn "" |
6651 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
6652 | (ashift:DI (match_operand:DI 1 "se_register_operand" "0,d") | |
6653 | (match_operand:SI 2 "arith_operand" "d,I")))] | |
6654 | "TARGET_64BIT && TARGET_MIPS16" | |
6655 | "* | |
6656 | { | |
6657 | if (which_alternative == 0) | |
6658 | return \"dsll\\t%0,%2\"; | |
6659 | ||
6660 | if (GET_CODE (operands[2]) == CONST_INT) | |
6661 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
6662 | ||
6663 | return \"dsll\\t%0,%1,%2\"; | |
6664 | }" | |
6665 | [(set_attr "type" "arith") | |
6666 | (set_attr "mode" "DI") | |
6667 | (set_attr_alternative "length" | |
0ff83799 | 6668 | [(const_int 4) |
2bcb2ab3 | 6669 | (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") |
0ff83799 MM |
6670 | (const_int 4) |
6671 | (const_int 8))])]) | |
2bcb2ab3 | 6672 | |
bb621ad7 | 6673 | |
2bcb2ab3 GK |
6674 | ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. |
6675 | ||
6676 | (define_split | |
6677 | [(set (match_operand:DI 0 "register_operand" "") | |
6678 | (ashift:DI (match_operand:DI 1 "register_operand" "") | |
6679 | (match_operand:SI 2 "const_int_operand" "")))] | |
6680 | "TARGET_MIPS16 && TARGET_64BIT | |
6681 | && reload_completed | |
6682 | && GET_CODE (operands[2]) == CONST_INT | |
6683 | && INTVAL (operands[2]) > 8 | |
6684 | && INTVAL (operands[2]) <= 16" | |
6685 | [(set (match_dup 0) (ashift:DI (match_dup 1) (const_int 8))) | |
6686 | (set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))] | |
6687 | " | |
6688 | { | |
6689 | operands[2] = GEN_INT (INTVAL (operands[2]) - 8); | |
6690 | }") | |
6691 | ||
6692 | (define_expand "ashrsi3" | |
8ef30996 MM |
6693 | [(set (match_operand:SI 0 "register_operand" "=d") |
6694 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") | |
6695 | (match_operand:SI 2 "arith_operand" "dI")))] | |
6696 | "" | |
2bcb2ab3 GK |
6697 | " |
6698 | { | |
6699 | /* On the mips16, a shift of more than 8 is a four byte instruction, | |
6700 | so, for a shift between 8 and 16, it is just as fast to do two | |
6701 | shifts of 8 or less. If there is a lot of shifting going on, we | |
6702 | may win in CSE. Otherwise combine will put the shifts back | |
6703 | together again. */ | |
6704 | if (TARGET_MIPS16 | |
6705 | && optimize | |
6706 | && GET_CODE (operands[2]) == CONST_INT | |
6707 | && INTVAL (operands[2]) > 8 | |
6708 | && INTVAL (operands[2]) <= 16) | |
6709 | { | |
6710 | rtx temp = gen_reg_rtx (SImode); | |
6711 | ||
6712 | emit_insn (gen_ashrsi3_internal2 (temp, operands[1], GEN_INT (8))); | |
6713 | emit_insn (gen_ashrsi3_internal2 (operands[0], temp, | |
6714 | GEN_INT (INTVAL (operands[2]) - 8))); | |
6715 | DONE; | |
6716 | } | |
6717 | }") | |
6718 | ||
6719 | (define_insn "ashrsi3_internal1" | |
6720 | [(set (match_operand:SI 0 "register_operand" "=d") | |
6721 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") | |
6722 | (match_operand:SI 2 "arith_operand" "dI")))] | |
6723 | "!TARGET_MIPS16" | |
8ef30996 MM |
6724 | "* |
6725 | { | |
6726 | if (GET_CODE (operands[2]) == CONST_INT) | |
2bcb2ab3 | 6727 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
8ef30996 MM |
6728 | |
6729 | return \"sra\\t%0,%1,%2\"; | |
6730 | }" | |
6731 | [(set_attr "type" "arith") | |
0ff83799 | 6732 | (set_attr "mode" "SI")]) |
8ef30996 | 6733 | |
2bcb2ab3 GK |
6734 | (define_insn "ashrsi3_internal2" |
6735 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
6736 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,d") | |
6737 | (match_operand:SI 2 "arith_operand" "d,I")))] | |
6738 | "TARGET_MIPS16" | |
6739 | "* | |
6740 | { | |
6741 | if (which_alternative == 0) | |
6742 | return \"sra\\t%0,%2\"; | |
6743 | ||
6744 | if (GET_CODE (operands[2]) == CONST_INT) | |
95936d18 | 6745 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
2bcb2ab3 GK |
6746 | |
6747 | return \"sra\\t%0,%1,%2\"; | |
6748 | }" | |
6749 | [(set_attr "type" "arith") | |
6750 | (set_attr "mode" "SI") | |
6751 | (set_attr_alternative "length" | |
0ff83799 | 6752 | [(const_int 4) |
2bcb2ab3 | 6753 | (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") |
0ff83799 MM |
6754 | (const_int 4) |
6755 | (const_int 8))])]) | |
2bcb2ab3 GK |
6756 | |
6757 | ||
6758 | ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. | |
6759 | ||
6760 | (define_split | |
6761 | [(set (match_operand:SI 0 "register_operand" "") | |
6762 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "") | |
6763 | (match_operand:SI 2 "const_int_operand" "")))] | |
6764 | "TARGET_MIPS16 | |
6765 | && reload_completed | |
6766 | && GET_CODE (operands[2]) == CONST_INT | |
6767 | && INTVAL (operands[2]) > 8 | |
6768 | && INTVAL (operands[2]) <= 16" | |
6769 | [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 8))) | |
6770 | (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))] | |
6771 | " | |
6772 | { | |
6773 | operands[2] = GEN_INT (INTVAL (operands[2]) - 8); | |
6774 | }") | |
8ef30996 MM |
6775 | |
6776 | (define_expand "ashrdi3" | |
6777 | [(parallel [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 | 6778 | (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "") |
8ef30996 MM |
6779 | (match_operand:SI 2 "arith_operand" ""))) |
6780 | (clobber (match_dup 3))])] | |
2bcb2ab3 | 6781 | "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" |
bb621ad7 JW |
6782 | " |
6783 | { | |
6784 | if (TARGET_64BIT) | |
6785 | { | |
2bcb2ab3 GK |
6786 | /* On the mips16, a shift of more than 8 is a four byte |
6787 | instruction, so, for a shift between 8 and 16, it is just as | |
6788 | fast to do two shifts of 8 or less. If there is a lot of | |
6789 | shifting going on, we may win in CSE. Otherwise combine will | |
6790 | put the shifts back together again. */ | |
6791 | if (TARGET_MIPS16 | |
6792 | && optimize | |
6793 | && GET_CODE (operands[2]) == CONST_INT | |
6794 | && INTVAL (operands[2]) > 8 | |
6795 | && INTVAL (operands[2]) <= 16) | |
6796 | { | |
6797 | rtx temp = gen_reg_rtx (DImode); | |
6798 | ||
6799 | emit_insn (gen_ashrdi3_internal4 (temp, operands[1], GEN_INT (8))); | |
6800 | emit_insn (gen_ashrdi3_internal4 (operands[0], temp, | |
6801 | GEN_INT (INTVAL (operands[2]) - 8))); | |
6802 | DONE; | |
6803 | } | |
6804 | ||
bb621ad7 JW |
6805 | emit_insn (gen_ashrdi3_internal4 (operands[0], operands[1], |
6806 | operands[2])); | |
6807 | DONE; | |
6808 | } | |
6809 | ||
6810 | operands[3] = gen_reg_rtx (SImode); | |
6811 | }") | |
8ef30996 MM |
6812 | |
6813 | ||
6814 | (define_insn "ashrdi3_internal" | |
0fb5ac6f | 6815 | [(set (match_operand:DI 0 "register_operand" "=&d") |
8ef30996 MM |
6816 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") |
6817 | (match_operand:SI 2 "register_operand" "d"))) | |
6818 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 | 6819 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" |
8ef30996 MM |
6820 | "* |
6821 | { | |
6822 | operands[4] = const0_rtx; | |
6823 | dslots_jump_total += 3; | |
6824 | dslots_jump_filled += 2; | |
6825 | ||
6826 | return \"sll\\t%3,%2,26\\n\\ | |
6827 | \\tbgez\\t%3,1f\\n\\ | |
6828 | \\tsra\\t%L0,%M1,%2\\n\\ | |
6829 | \\t%(b\\t3f\\n\\ | |
6830 | \\tsra\\t%M0,%M1,31%)\\n\\ | |
6831 | \\n\\ | |
efa3896a | 6832 | %~1:\\n\\ |
8ef30996 MM |
6833 | \\t%(beq\\t%3,%z4,2f\\n\\ |
6834 | \\tsrl\\t%L0,%L1,%2%)\\n\\ | |
6835 | \\n\\ | |
6836 | \\tsubu\\t%3,%z4,%2\\n\\ | |
6837 | \\tsll\\t%3,%M1,%3\\n\\ | |
6838 | \\tor\\t%L0,%L0,%3\\n\\ | |
efa3896a | 6839 | %~2:\\n\\ |
8ef30996 | 6840 | \\tsra\\t%M0,%M1,%2\\n\\ |
efa3896a | 6841 | %~3:\"; |
8ef30996 MM |
6842 | }" |
6843 | [(set_attr "type" "darith") | |
6844 | (set_attr "mode" "DI") | |
0ff83799 | 6845 | (set_attr "length" "48")]) |
8ef30996 MM |
6846 | |
6847 | ||
6848 | (define_insn "ashrdi3_internal2" | |
6849 | [(set (match_operand:DI 0 "register_operand" "=d") | |
6850 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") | |
6851 | (match_operand:SI 2 "small_int" "IJK"))) | |
6852 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
bb621ad7 | 6853 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && (INTVAL (operands[2]) & 32) != 0" |
8ef30996 MM |
6854 | "* |
6855 | { | |
95936d18 | 6856 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
8ef30996 MM |
6857 | return \"sra\\t%L0,%M1,%2\;sra\\t%M0,%M1,31\"; |
6858 | }" | |
6859 | [(set_attr "type" "darith") | |
6860 | (set_attr "mode" "DI") | |
0ff83799 | 6861 | (set_attr "length" "8")]) |
8ef30996 MM |
6862 | |
6863 | ||
6864 | (define_split | |
6865 | [(set (match_operand:DI 0 "register_operand" "") | |
6866 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "") | |
6867 | (match_operand:SI 2 "small_int" ""))) | |
6868 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
bb621ad7 | 6869 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
8ef30996 MM |
6870 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
6871 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
6872 | && (INTVAL (operands[2]) & 32) != 0" | |
6873 | ||
ddef6bc7 JJ |
6874 | [(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2))) |
6875 | (set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (const_int 31)))] | |
8ef30996 | 6876 | |
95936d18 | 6877 | "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") |
8ef30996 MM |
6878 | |
6879 | ||
6880 | (define_split | |
6881 | [(set (match_operand:DI 0 "register_operand" "") | |
6882 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "") | |
6883 | (match_operand:SI 2 "small_int" ""))) | |
6884 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
bb621ad7 | 6885 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE |
8ef30996 MM |
6886 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
6887 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
6888 | && (INTVAL (operands[2]) & 32) != 0" | |
6889 | ||
ddef6bc7 | 6890 | [(set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) |
8ef30996 MM |
6891 | (set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (const_int 31)))] |
6892 | ||
95936d18 | 6893 | "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") |
8ef30996 MM |
6894 | |
6895 | ||
6896 | (define_insn "ashrdi3_internal3" | |
6897 | [(set (match_operand:DI 0 "register_operand" "=d") | |
6898 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") | |
6899 | (match_operand:SI 2 "small_int" "IJK"))) | |
6900 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 | 6901 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 |
8ef30996 MM |
6902 | && (INTVAL (operands[2]) & 63) < 32 |
6903 | && (INTVAL (operands[2]) & 63) != 0" | |
6904 | "* | |
6905 | { | |
6906 | int amount = INTVAL (operands[2]); | |
6907 | ||
c5c76735 JL |
6908 | operands[2] = GEN_INT (amount & 31); |
6909 | operands[4] = GEN_INT ((-amount) & 31); | |
8ef30996 MM |
6910 | |
6911 | return \"srl\\t%L0,%L1,%2\;sll\\t%3,%M1,%4\;or\\t%L0,%L0,%3\;sra\\t%M0,%M1,%2\"; | |
6912 | }" | |
6913 | [(set_attr "type" "darith") | |
6914 | (set_attr "mode" "DI") | |
0ff83799 | 6915 | (set_attr "length" "16")]) |
8ef30996 MM |
6916 | |
6917 | ||
6918 | (define_split | |
6919 | [(set (match_operand:DI 0 "register_operand" "") | |
6920 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "") | |
6921 | (match_operand:SI 2 "small_int" ""))) | |
6922 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
6923 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
6924 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
6925 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
6926 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
6927 | && (INTVAL (operands[2]) & 63) < 32 | |
6928 | && (INTVAL (operands[2]) & 63) != 0" | |
6929 | ||
6930 | [(set (subreg:SI (match_dup 0) 0) | |
6931 | (lshiftrt:SI (subreg:SI (match_dup 1) 0) | |
6932 | (match_dup 2))) | |
6933 | ||
6934 | (set (match_dup 3) | |
ddef6bc7 | 6935 | (ashift:SI (subreg:SI (match_dup 1) 4) |
8ef30996 MM |
6936 | (match_dup 4))) |
6937 | ||
6938 | (set (subreg:SI (match_dup 0) 0) | |
6939 | (ior:SI (subreg:SI (match_dup 0) 0) | |
6940 | (match_dup 3))) | |
6941 | ||
ddef6bc7 JJ |
6942 | (set (subreg:SI (match_dup 0) 4) |
6943 | (ashiftrt:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
6944 | (match_dup 2)))] |
6945 | " | |
6946 | { | |
6947 | int amount = INTVAL (operands[2]); | |
c5c76735 JL |
6948 | operands[2] = GEN_INT (amount & 31); |
6949 | operands[4] = GEN_INT ((-amount) & 31); | |
8ef30996 MM |
6950 | }") |
6951 | ||
6952 | ||
6953 | (define_split | |
6954 | [(set (match_operand:DI 0 "register_operand" "") | |
6955 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "") | |
6956 | (match_operand:SI 2 "small_int" ""))) | |
6957 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
6958 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
6959 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
6960 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
6961 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
6962 | && (INTVAL (operands[2]) & 63) < 32 | |
6963 | && (INTVAL (operands[2]) & 63) != 0" | |
6964 | ||
ddef6bc7 JJ |
6965 | [(set (subreg:SI (match_dup 0) 4) |
6966 | (lshiftrt:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
6967 | (match_dup 2))) |
6968 | ||
6969 | (set (match_dup 3) | |
6970 | (ashift:SI (subreg:SI (match_dup 1) 0) | |
6971 | (match_dup 4))) | |
6972 | ||
ddef6bc7 JJ |
6973 | (set (subreg:SI (match_dup 0) 4) |
6974 | (ior:SI (subreg:SI (match_dup 0) 4) | |
8ef30996 MM |
6975 | (match_dup 3))) |
6976 | ||
6977 | (set (subreg:SI (match_dup 0) 0) | |
6978 | (ashiftrt:SI (subreg:SI (match_dup 1) 0) | |
6979 | (match_dup 2)))] | |
6980 | " | |
6981 | { | |
6982 | int amount = INTVAL (operands[2]); | |
c5c76735 JL |
6983 | operands[2] = GEN_INT (amount & 31); |
6984 | operands[4] = GEN_INT ((-amount) & 31); | |
8ef30996 MM |
6985 | }") |
6986 | ||
6987 | ||
bb621ad7 JW |
6988 | (define_insn "ashrdi3_internal4" |
6989 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 6990 | (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "d") |
bb621ad7 | 6991 | (match_operand:SI 2 "arith_operand" "dI")))] |
2bcb2ab3 | 6992 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
6993 | "* |
6994 | { | |
6995 | if (GET_CODE (operands[2]) == CONST_INT) | |
6996 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
6997 | ||
6998 | return \"dsra\\t%0,%1,%2\"; | |
6999 | }" | |
7000 | [(set_attr "type" "arith") | |
0ff83799 | 7001 | (set_attr "mode" "DI")]) |
bb621ad7 | 7002 | |
2bcb2ab3 GK |
7003 | (define_insn "" |
7004 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
7005 | (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "0,0") | |
7006 | (match_operand:SI 2 "arith_operand" "d,I")))] | |
7007 | "TARGET_64BIT && TARGET_MIPS16" | |
7008 | "* | |
7009 | { | |
7010 | if (GET_CODE (operands[2]) == CONST_INT) | |
7011 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
7012 | ||
7013 | return \"dsra\\t%0,%2\"; | |
7014 | }" | |
7015 | [(set_attr "type" "arith") | |
7016 | (set_attr "mode" "DI") | |
7017 | (set_attr_alternative "length" | |
0ff83799 | 7018 | [(const_int 4) |
2bcb2ab3 | 7019 | (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") |
0ff83799 MM |
7020 | (const_int 4) |
7021 | (const_int 8))])]) | |
2bcb2ab3 GK |
7022 | |
7023 | ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. | |
bb621ad7 | 7024 | |
2bcb2ab3 GK |
7025 | (define_split |
7026 | [(set (match_operand:DI 0 "register_operand" "") | |
7027 | (ashiftrt:DI (match_operand:DI 1 "register_operand" "") | |
7028 | (match_operand:SI 2 "const_int_operand" "")))] | |
7029 | "TARGET_MIPS16 && TARGET_64BIT | |
7030 | && reload_completed | |
7031 | && GET_CODE (operands[2]) == CONST_INT | |
7032 | && INTVAL (operands[2]) > 8 | |
7033 | && INTVAL (operands[2]) <= 16" | |
7034 | [(set (match_dup 0) (ashiftrt:DI (match_dup 1) (const_int 8))) | |
7035 | (set (match_dup 0) (ashiftrt:DI (match_dup 0) (match_dup 2)))] | |
7036 | " | |
7037 | { | |
7038 | operands[2] = GEN_INT (INTVAL (operands[2]) - 8); | |
7039 | }") | |
7040 | ||
7041 | (define_expand "lshrsi3" | |
8ef30996 MM |
7042 | [(set (match_operand:SI 0 "register_operand" "=d") |
7043 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") | |
7044 | (match_operand:SI 2 "arith_operand" "dI")))] | |
7045 | "" | |
2bcb2ab3 GK |
7046 | " |
7047 | { | |
7048 | /* On the mips16, a shift of more than 8 is a four byte instruction, | |
7049 | so, for a shift between 8 and 16, it is just as fast to do two | |
7050 | shifts of 8 or less. If there is a lot of shifting going on, we | |
7051 | may win in CSE. Otherwise combine will put the shifts back | |
7052 | together again. */ | |
7053 | if (TARGET_MIPS16 | |
7054 | && optimize | |
7055 | && GET_CODE (operands[2]) == CONST_INT | |
7056 | && INTVAL (operands[2]) > 8 | |
7057 | && INTVAL (operands[2]) <= 16) | |
7058 | { | |
7059 | rtx temp = gen_reg_rtx (SImode); | |
7060 | ||
7061 | emit_insn (gen_lshrsi3_internal2 (temp, operands[1], GEN_INT (8))); | |
7062 | emit_insn (gen_lshrsi3_internal2 (operands[0], temp, | |
7063 | GEN_INT (INTVAL (operands[2]) - 8))); | |
7064 | DONE; | |
7065 | } | |
7066 | }") | |
7067 | ||
7068 | (define_insn "lshrsi3_internal1" | |
7069 | [(set (match_operand:SI 0 "register_operand" "=d") | |
7070 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") | |
7071 | (match_operand:SI 2 "arith_operand" "dI")))] | |
7072 | "!TARGET_MIPS16" | |
8ef30996 MM |
7073 | "* |
7074 | { | |
7075 | if (GET_CODE (operands[2]) == CONST_INT) | |
95936d18 | 7076 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
8ef30996 MM |
7077 | |
7078 | return \"srl\\t%0,%1,%2\"; | |
7079 | }" | |
7080 | [(set_attr "type" "arith") | |
0ff83799 | 7081 | (set_attr "mode" "SI")]) |
8ef30996 | 7082 | |
2bcb2ab3 GK |
7083 | (define_insn "lshrsi3_internal2" |
7084 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
7085 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,d") | |
7086 | (match_operand:SI 2 "arith_operand" "d,I")))] | |
7087 | "TARGET_MIPS16" | |
7088 | "* | |
7089 | { | |
7090 | if (which_alternative == 0) | |
7091 | return \"srl\\t%0,%2\"; | |
7092 | ||
7093 | if (GET_CODE (operands[2]) == CONST_INT) | |
95936d18 | 7094 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
2bcb2ab3 GK |
7095 | |
7096 | return \"srl\\t%0,%1,%2\"; | |
7097 | }" | |
7098 | [(set_attr "type" "arith") | |
7099 | (set_attr "mode" "SI") | |
7100 | (set_attr_alternative "length" | |
0ff83799 | 7101 | [(const_int 4) |
2bcb2ab3 | 7102 | (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") |
0ff83799 MM |
7103 | (const_int 4) |
7104 | (const_int 8))])]) | |
2bcb2ab3 GK |
7105 | |
7106 | ||
7107 | ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. | |
7108 | ||
7109 | (define_split | |
7110 | [(set (match_operand:SI 0 "register_operand" "") | |
7111 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "") | |
7112 | (match_operand:SI 2 "const_int_operand" "")))] | |
7113 | "TARGET_MIPS16 | |
7114 | && reload_completed | |
7115 | && GET_CODE (operands[2]) == CONST_INT | |
7116 | && INTVAL (operands[2]) > 8 | |
7117 | && INTVAL (operands[2]) <= 16" | |
7118 | [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 8))) | |
7119 | (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))] | |
7120 | " | |
7121 | { | |
7122 | operands[2] = GEN_INT (INTVAL (operands[2]) - 8); | |
7123 | }") | |
7124 | ||
7125 | ;; If we load a byte on the mips16 as a bitfield, the resulting | |
7126 | ;; sequence of instructions is too complicated for combine, because it | |
7127 | ;; involves four instructions: a load, a shift, a constant load into a | |
7128 | ;; register, and an and (the key problem here is that the mips16 does | |
7129 | ;; not have and immediate). We recognize a shift of a load in order | |
7130 | ;; to make it simple enough for combine to understand. | |
7131 | ||
7132 | (define_insn "" | |
1379191a | 7133 | [(set (match_operand:SI 0 "register_operand" "=d,d") |
2bcb2ab3 GK |
7134 | (lshiftrt:SI (match_operand:SI 1 "memory_operand" "R,m") |
7135 | (match_operand:SI 2 "immediate_operand" "I,I")))] | |
7136 | "TARGET_MIPS16" | |
7137 | "lw\\t%0,%1\;srl\\t%0,%2" | |
7138 | [(set_attr "type" "load") | |
7139 | (set_attr "mode" "SI") | |
7140 | (set_attr_alternative "length" | |
7141 | [(if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") | |
0ff83799 MM |
7142 | (const_int 8) |
7143 | (const_int 12)) | |
2bcb2ab3 | 7144 | (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") |
0ff83799 MM |
7145 | (const_int 12) |
7146 | (const_int 16))])]) | |
2bcb2ab3 GK |
7147 | |
7148 | (define_split | |
7149 | [(set (match_operand:SI 0 "register_operand" "") | |
7150 | (lshiftrt:SI (match_operand:SI 1 "memory_operand" "") | |
7151 | (match_operand:SI 2 "immediate_operand" "")))] | |
7152 | "TARGET_MIPS16" | |
7153 | [(set (match_dup 0) (match_dup 1)) | |
7154 | (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))] | |
7155 | "") | |
8ef30996 MM |
7156 | |
7157 | (define_expand "lshrdi3" | |
7158 | [(parallel [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 | 7159 | (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "") |
8ef30996 MM |
7160 | (match_operand:SI 2 "arith_operand" ""))) |
7161 | (clobber (match_dup 3))])] | |
2bcb2ab3 | 7162 | "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" |
bb621ad7 JW |
7163 | " |
7164 | { | |
7165 | if (TARGET_64BIT) | |
7166 | { | |
2bcb2ab3 GK |
7167 | /* On the mips16, a shift of more than 8 is a four byte |
7168 | instruction, so, for a shift between 8 and 16, it is just as | |
7169 | fast to do two shifts of 8 or less. If there is a lot of | |
7170 | shifting going on, we may win in CSE. Otherwise combine will | |
7171 | put the shifts back together again. */ | |
7172 | if (TARGET_MIPS16 | |
7173 | && optimize | |
7174 | && GET_CODE (operands[2]) == CONST_INT | |
7175 | && INTVAL (operands[2]) > 8 | |
7176 | && INTVAL (operands[2]) <= 16) | |
7177 | { | |
7178 | rtx temp = gen_reg_rtx (DImode); | |
7179 | ||
7180 | emit_insn (gen_lshrdi3_internal4 (temp, operands[1], GEN_INT (8))); | |
7181 | emit_insn (gen_lshrdi3_internal4 (operands[0], temp, | |
7182 | GEN_INT (INTVAL (operands[2]) - 8))); | |
7183 | DONE; | |
7184 | } | |
7185 | ||
bb621ad7 JW |
7186 | emit_insn (gen_lshrdi3_internal4 (operands[0], operands[1], |
7187 | operands[2])); | |
7188 | DONE; | |
7189 | } | |
7190 | ||
7191 | operands[3] = gen_reg_rtx (SImode); | |
7192 | }") | |
8ef30996 MM |
7193 | |
7194 | ||
7195 | (define_insn "lshrdi3_internal" | |
7196 | [(set (match_operand:DI 0 "register_operand" "=&d") | |
7197 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") | |
7198 | (match_operand:SI 2 "register_operand" "d"))) | |
7199 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 | 7200 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" |
8ef30996 MM |
7201 | "* |
7202 | { | |
7203 | operands[4] = const0_rtx; | |
7204 | dslots_jump_total += 3; | |
7205 | dslots_jump_filled += 2; | |
7206 | ||
7207 | return \"sll\\t%3,%2,26\\n\\ | |
7208 | \\tbgez\\t%3,1f\\n\\ | |
7209 | \\tsrl\\t%L0,%M1,%2\\n\\ | |
7210 | \\t%(b\\t3f\\n\\ | |
7211 | \\tmove\\t%M0,%z4%)\\n\\ | |
7212 | \\n\\ | |
efa3896a | 7213 | %~1:\\n\\ |
8ef30996 MM |
7214 | \\t%(beq\\t%3,%z4,2f\\n\\ |
7215 | \\tsrl\\t%L0,%L1,%2%)\\n\\ | |
7216 | \\n\\ | |
7217 | \\tsubu\\t%3,%z4,%2\\n\\ | |
7218 | \\tsll\\t%3,%M1,%3\\n\\ | |
7219 | \\tor\\t%L0,%L0,%3\\n\\ | |
efa3896a | 7220 | %~2:\\n\\ |
8ef30996 | 7221 | \\tsrl\\t%M0,%M1,%2\\n\\ |
efa3896a | 7222 | %~3:\"; |
8ef30996 MM |
7223 | }" |
7224 | [(set_attr "type" "darith") | |
7225 | (set_attr "mode" "DI") | |
0ff83799 | 7226 | (set_attr "length" "48")]) |
8ef30996 MM |
7227 | |
7228 | ||
7229 | (define_insn "lshrdi3_internal2" | |
7230 | [(set (match_operand:DI 0 "register_operand" "=d") | |
7231 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") | |
7232 | (match_operand:SI 2 "small_int" "IJK"))) | |
7233 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 GK |
7234 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 |
7235 | && (INTVAL (operands[2]) & 32) != 0" | |
8ef30996 MM |
7236 | "* |
7237 | { | |
95936d18 | 7238 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); |
8ef30996 MM |
7239 | operands[4] = const0_rtx; |
7240 | return \"srl\\t%L0,%M1,%2\;move\\t%M0,%z4\"; | |
7241 | }" | |
7242 | [(set_attr "type" "darith") | |
7243 | (set_attr "mode" "DI") | |
0ff83799 | 7244 | (set_attr "length" "8")]) |
8ef30996 MM |
7245 | |
7246 | ||
7247 | (define_split | |
7248 | [(set (match_operand:DI 0 "register_operand" "") | |
7249 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "") | |
7250 | (match_operand:SI 2 "small_int" ""))) | |
7251 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
7252 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
7253 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
7254 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
7255 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
7256 | && (INTVAL (operands[2]) & 32) != 0" | |
7257 | ||
ddef6bc7 JJ |
7258 | [(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2))) |
7259 | (set (subreg:SI (match_dup 0) 4) (const_int 0))] | |
8ef30996 | 7260 | |
95936d18 | 7261 | "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") |
8ef30996 MM |
7262 | |
7263 | ||
7264 | (define_split | |
7265 | [(set (match_operand:DI 0 "register_operand" "") | |
7266 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "") | |
7267 | (match_operand:SI 2 "small_int" ""))) | |
7268 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
7269 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
7270 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
7271 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
7272 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
7273 | && (INTVAL (operands[2]) & 32) != 0" | |
7274 | ||
ddef6bc7 | 7275 | [(set (subreg:SI (match_dup 0) 4) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) |
8ef30996 MM |
7276 | (set (subreg:SI (match_dup 0) 0) (const_int 0))] |
7277 | ||
95936d18 | 7278 | "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") |
8ef30996 MM |
7279 | |
7280 | ||
7281 | (define_insn "lshrdi3_internal3" | |
7282 | [(set (match_operand:DI 0 "register_operand" "=d") | |
7283 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") | |
7284 | (match_operand:SI 2 "small_int" "IJK"))) | |
7285 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
2bcb2ab3 | 7286 | "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 |
8ef30996 MM |
7287 | && (INTVAL (operands[2]) & 63) < 32 |
7288 | && (INTVAL (operands[2]) & 63) != 0" | |
7289 | "* | |
7290 | { | |
7291 | int amount = INTVAL (operands[2]); | |
7292 | ||
c5c76735 JL |
7293 | operands[2] = GEN_INT (amount & 31); |
7294 | operands[4] = GEN_INT ((-amount) & 31); | |
8ef30996 MM |
7295 | |
7296 | return \"srl\\t%L0,%L1,%2\;sll\\t%3,%M1,%4\;or\\t%L0,%L0,%3\;srl\\t%M0,%M1,%2\"; | |
7297 | }" | |
7298 | [(set_attr "type" "darith") | |
7299 | (set_attr "mode" "DI") | |
0ff83799 | 7300 | (set_attr "length" "16")]) |
8ef30996 MM |
7301 | |
7302 | ||
7303 | (define_split | |
7304 | [(set (match_operand:DI 0 "register_operand" "") | |
7305 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "") | |
7306 | (match_operand:SI 2 "small_int" ""))) | |
7307 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
7308 | "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT |
7309 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
7310 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
7311 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
7312 | && (INTVAL (operands[2]) & 63) < 32 | |
7313 | && (INTVAL (operands[2]) & 63) != 0" | |
7314 | ||
7315 | [(set (subreg:SI (match_dup 0) 0) | |
7316 | (lshiftrt:SI (subreg:SI (match_dup 1) 0) | |
7317 | (match_dup 2))) | |
7318 | ||
7319 | (set (match_dup 3) | |
ddef6bc7 | 7320 | (ashift:SI (subreg:SI (match_dup 1) 4) |
8ef30996 MM |
7321 | (match_dup 4))) |
7322 | ||
7323 | (set (subreg:SI (match_dup 0) 0) | |
7324 | (ior:SI (subreg:SI (match_dup 0) 0) | |
7325 | (match_dup 3))) | |
7326 | ||
ddef6bc7 JJ |
7327 | (set (subreg:SI (match_dup 0) 4) |
7328 | (lshiftrt:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
7329 | (match_dup 2)))] |
7330 | " | |
7331 | { | |
7332 | int amount = INTVAL (operands[2]); | |
c5c76735 JL |
7333 | operands[2] = GEN_INT (amount & 31); |
7334 | operands[4] = GEN_INT ((-amount) & 31); | |
8ef30996 MM |
7335 | }") |
7336 | ||
7337 | ||
7338 | (define_split | |
7339 | [(set (match_operand:DI 0 "register_operand" "") | |
7340 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "") | |
7341 | (match_operand:SI 2 "small_int" ""))) | |
7342 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
2bcb2ab3 GK |
7343 | "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT |
7344 | && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 | |
8ef30996 MM |
7345 | && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER |
7346 | && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER | |
7347 | && (INTVAL (operands[2]) & 63) < 32 | |
7348 | && (INTVAL (operands[2]) & 63) != 0" | |
7349 | ||
ddef6bc7 JJ |
7350 | [(set (subreg:SI (match_dup 0) 4) |
7351 | (lshiftrt:SI (subreg:SI (match_dup 1) 4) | |
8ef30996 MM |
7352 | (match_dup 2))) |
7353 | ||
7354 | (set (match_dup 3) | |
7355 | (ashift:SI (subreg:SI (match_dup 1) 0) | |
7356 | (match_dup 4))) | |
7357 | ||
ddef6bc7 JJ |
7358 | (set (subreg:SI (match_dup 0) 4) |
7359 | (ior:SI (subreg:SI (match_dup 0) 4) | |
8ef30996 MM |
7360 | (match_dup 3))) |
7361 | ||
7362 | (set (subreg:SI (match_dup 0) 0) | |
7363 | (lshiftrt:SI (subreg:SI (match_dup 1) 0) | |
7364 | (match_dup 2)))] | |
7365 | " | |
7366 | { | |
7367 | int amount = INTVAL (operands[2]); | |
c5c76735 JL |
7368 | operands[2] = GEN_INT (amount & 31); |
7369 | operands[4] = GEN_INT ((-amount) & 31); | |
8ef30996 MM |
7370 | }") |
7371 | ||
bb621ad7 JW |
7372 | |
7373 | (define_insn "lshrdi3_internal4" | |
7374 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 7375 | (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "d") |
bb621ad7 | 7376 | (match_operand:SI 2 "arith_operand" "dI")))] |
2bcb2ab3 | 7377 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
7378 | "* |
7379 | { | |
7380 | if (GET_CODE (operands[2]) == CONST_INT) | |
7381 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
7382 | ||
7383 | return \"dsrl\\t%0,%1,%2\"; | |
7384 | }" | |
7385 | [(set_attr "type" "arith") | |
0ff83799 | 7386 | (set_attr "mode" "DI")]) |
bb621ad7 | 7387 | |
2bcb2ab3 GK |
7388 | (define_insn "" |
7389 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
7390 | (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "0,0") | |
7391 | (match_operand:SI 2 "arith_operand" "d,I")))] | |
7392 | "TARGET_64BIT && TARGET_MIPS16" | |
7393 | "* | |
7394 | { | |
7395 | if (GET_CODE (operands[2]) == CONST_INT) | |
7396 | operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); | |
7397 | ||
7398 | return \"dsrl\\t%0,%2\"; | |
7399 | }" | |
7400 | [(set_attr "type" "arith") | |
7401 | (set_attr "mode" "DI") | |
7402 | (set_attr_alternative "length" | |
0ff83799 | 7403 | [(const_int 4) |
2bcb2ab3 | 7404 | (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") |
0ff83799 MM |
7405 | (const_int 4) |
7406 | (const_int 8))])]) | |
2bcb2ab3 GK |
7407 | |
7408 | ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. | |
7409 | ||
7410 | (define_split | |
7411 | [(set (match_operand:DI 0 "register_operand" "") | |
7412 | (lshiftrt:DI (match_operand:DI 1 "register_operand" "") | |
7413 | (match_operand:SI 2 "const_int_operand" "")))] | |
7414 | "TARGET_MIPS16 | |
7415 | && reload_completed | |
7416 | && GET_CODE (operands[2]) == CONST_INT | |
7417 | && INTVAL (operands[2]) > 8 | |
7418 | && INTVAL (operands[2]) <= 16" | |
7419 | [(set (match_dup 0) (lshiftrt:DI (match_dup 1) (const_int 8))) | |
7420 | (set (match_dup 0) (lshiftrt:DI (match_dup 0) (match_dup 2)))] | |
7421 | " | |
7422 | { | |
7423 | operands[2] = GEN_INT (INTVAL (operands[2]) - 8); | |
7424 | }") | |
7425 | ||
8ef30996 MM |
7426 | \f |
7427 | ;; | |
7428 | ;; .................... | |
7429 | ;; | |
7430 | ;; COMPARISONS | |
7431 | ;; | |
7432 | ;; .................... | |
7433 | ||
7434 | ;; Flow here is rather complex: | |
7435 | ;; | |
bb621ad7 | 7436 | ;; 1) The cmp{si,di,sf,df} routine is called. It deposits the |
8ef30996 MM |
7437 | ;; arguments into the branch_cmp array, and the type into |
7438 | ;; branch_type. No RTL is generated. | |
7439 | ;; | |
7440 | ;; 2) The appropriate branch define_expand is called, which then | |
7441 | ;; creates the appropriate RTL for the comparison and branch. | |
7442 | ;; Different CC modes are used, based on what type of branch is | |
7443 | ;; done, so that we can constrain things appropriately. There | |
7444 | ;; are assumptions in the rest of GCC that break if we fold the | |
7445 | ;; operands into the branchs for integer operations, and use cc0 | |
34b650b3 MM |
7446 | ;; for floating point, so we use the fp status register instead. |
7447 | ;; If needed, an appropriate temporary is created to hold the | |
7448 | ;; of the integer compare. | |
8ef30996 MM |
7449 | |
7450 | (define_expand "cmpsi" | |
7451 | [(set (cc0) | |
7452 | (compare:CC (match_operand:SI 0 "register_operand" "") | |
7453 | (match_operand:SI 1 "arith_operand" "")))] | |
7454 | "" | |
7455 | " | |
7456 | { | |
7457 | if (operands[0]) /* avoid unused code message */ | |
7458 | { | |
7459 | branch_cmp[0] = operands[0]; | |
7460 | branch_cmp[1] = operands[1]; | |
7461 | branch_type = CMP_SI; | |
7462 | DONE; | |
7463 | } | |
7464 | }") | |
7465 | ||
7466 | (define_expand "tstsi" | |
7467 | [(set (cc0) | |
7468 | (match_operand:SI 0 "register_operand" ""))] | |
7469 | "" | |
7470 | " | |
7471 | { | |
7472 | if (operands[0]) /* avoid unused code message */ | |
7473 | { | |
7474 | branch_cmp[0] = operands[0]; | |
7475 | branch_cmp[1] = const0_rtx; | |
7476 | branch_type = CMP_SI; | |
7477 | DONE; | |
7478 | } | |
7479 | }") | |
7480 | ||
bb621ad7 JW |
7481 | (define_expand "cmpdi" |
7482 | [(set (cc0) | |
1908a152 ILT |
7483 | (compare:CC (match_operand:DI 0 "se_register_operand" "") |
7484 | (match_operand:DI 1 "se_arith_operand" "")))] | |
bb621ad7 JW |
7485 | "TARGET_64BIT" |
7486 | " | |
7487 | { | |
7488 | if (operands[0]) /* avoid unused code message */ | |
7489 | { | |
7490 | branch_cmp[0] = operands[0]; | |
7491 | branch_cmp[1] = operands[1]; | |
7492 | branch_type = CMP_DI; | |
7493 | DONE; | |
7494 | } | |
7495 | }") | |
7496 | ||
7497 | (define_expand "tstdi" | |
7498 | [(set (cc0) | |
1908a152 | 7499 | (match_operand:DI 0 "se_register_operand" ""))] |
bb621ad7 JW |
7500 | "TARGET_64BIT" |
7501 | " | |
7502 | { | |
7503 | if (operands[0]) /* avoid unused code message */ | |
7504 | { | |
7505 | branch_cmp[0] = operands[0]; | |
7506 | branch_cmp[1] = const0_rtx; | |
7507 | branch_type = CMP_DI; | |
7508 | DONE; | |
7509 | } | |
7510 | }") | |
7511 | ||
8ef30996 MM |
7512 | (define_expand "cmpdf" |
7513 | [(set (cc0) | |
b8eb88d0 ILT |
7514 | (compare:CC (match_operand:DF 0 "register_operand" "") |
7515 | (match_operand:DF 1 "register_operand" "")))] | |
46299de9 | 7516 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
8ef30996 MM |
7517 | " |
7518 | { | |
7519 | if (operands[0]) /* avoid unused code message */ | |
7520 | { | |
7521 | branch_cmp[0] = operands[0]; | |
7522 | branch_cmp[1] = operands[1]; | |
7523 | branch_type = CMP_DF; | |
7524 | DONE; | |
7525 | } | |
7526 | }") | |
7527 | ||
8ef30996 MM |
7528 | (define_expand "cmpsf" |
7529 | [(set (cc0) | |
b8eb88d0 ILT |
7530 | (compare:CC (match_operand:SF 0 "register_operand" "") |
7531 | (match_operand:SF 1 "register_operand" "")))] | |
8ef30996 MM |
7532 | "TARGET_HARD_FLOAT" |
7533 | " | |
7534 | { | |
7535 | if (operands[0]) /* avoid unused code message */ | |
7536 | { | |
7537 | branch_cmp[0] = operands[0]; | |
7538 | branch_cmp[1] = operands[1]; | |
7539 | branch_type = CMP_SF; | |
7540 | DONE; | |
7541 | } | |
7542 | }") | |
7543 | ||
8ef30996 MM |
7544 | \f |
7545 | ;; | |
7546 | ;; .................... | |
7547 | ;; | |
7548 | ;; CONDITIONAL BRANCHES | |
7549 | ;; | |
7550 | ;; .................... | |
7551 | ||
0ff83799 MM |
7552 | ;; Conditional branches on floating-point equality tests. |
7553 | ||
7554 | (define_insn "branch_fp" | |
8ef30996 | 7555 | [(set (pc) |
0ff83799 MM |
7556 | (if_then_else |
7557 | (match_operator:CC 0 "cmp_op" | |
7558 | [(match_operand:CC 2 "register_operand" "z") | |
7559 | (const_int 0)]) | |
7560 | (label_ref (match_operand 1 "" "")) | |
7561 | (pc)))] | |
bb621ad7 | 7562 | "TARGET_HARD_FLOAT" |
8ef30996 MM |
7563 | "* |
7564 | { | |
0ff83799 MM |
7565 | return mips_output_conditional_branch (insn, |
7566 | operands, | |
7567 | /*two_operands_p=*/0, | |
7568 | /*float_p=*/1, | |
7569 | /*inverted_p=*/0, | |
7570 | get_attr_length (insn)); | |
8ef30996 MM |
7571 | }" |
7572 | [(set_attr "type" "branch") | |
0ff83799 | 7573 | (set_attr "mode" "none")]) |
8ef30996 | 7574 | |
0ff83799 | 7575 | (define_insn "branch_fp_inverted" |
8ef30996 | 7576 | [(set (pc) |
0ff83799 MM |
7577 | (if_then_else |
7578 | (match_operator:CC 0 "cmp_op" | |
7579 | [(match_operand:CC 2 "register_operand" "z") | |
7580 | (const_int 0)]) | |
7581 | (pc) | |
7582 | (label_ref (match_operand 1 "" ""))))] | |
bb621ad7 | 7583 | "TARGET_HARD_FLOAT" |
8ef30996 MM |
7584 | "* |
7585 | { | |
0ff83799 MM |
7586 | return mips_output_conditional_branch (insn, |
7587 | operands, | |
7588 | /*two_operands_p=*/0, | |
7589 | /*float_p=*/1, | |
7590 | /*inverted_p=*/1, | |
7591 | get_attr_length (insn)); | |
8ef30996 MM |
7592 | }" |
7593 | [(set_attr "type" "branch") | |
0ff83799 MM |
7594 | (set_attr "mode" "none")]) |
7595 | ||
7596 | ;; Conditional branches on comparisons with zero. | |
8ef30996 | 7597 | |
34b650b3 | 7598 | (define_insn "branch_zero" |
8ef30996 | 7599 | [(set (pc) |
0ff83799 MM |
7600 | (if_then_else |
7601 | (match_operator:SI 0 "cmp_op" | |
7602 | [(match_operand:SI 2 "register_operand" "d") | |
7603 | (const_int 0)]) | |
7604 | (label_ref (match_operand 1 "" "")) | |
7605 | (pc)))] | |
2bcb2ab3 | 7606 | "!TARGET_MIPS16" |
8ef30996 MM |
7607 | "* |
7608 | { | |
0ff83799 MM |
7609 | return mips_output_conditional_branch (insn, |
7610 | operands, | |
7611 | /*two_operands_p=*/0, | |
7612 | /*float_p=*/0, | |
7613 | /*inverted_p=*/0, | |
7614 | get_attr_length (insn)); | |
7615 | }" | |
7616 | [(set_attr "type" "branch") | |
7617 | (set_attr "mode" "none")]) | |
8ef30996 | 7618 | |
0ff83799 MM |
7619 | (define_insn "branch_zero_inverted" |
7620 | [(set (pc) | |
7621 | (if_then_else | |
7622 | (match_operator:SI 0 "cmp_op" | |
7623 | [(match_operand:SI 2 "register_operand" "d") | |
7624 | (const_int 0)]) | |
7625 | (pc) | |
7626 | (label_ref (match_operand 1 "" ""))))] | |
7627 | "!TARGET_MIPS16" | |
7628 | "* | |
7629 | { | |
7630 | return mips_output_conditional_branch (insn, | |
7631 | operands, | |
7632 | /*two_operands_p=*/0, | |
7633 | /*float_p=*/0, | |
7634 | /*inverted_p=*/1, | |
7635 | get_attr_length (insn)); | |
7636 | }" | |
7637 | [(set_attr "type" "branch") | |
7638 | (set_attr "mode" "none")]) | |
8ef30996 | 7639 | |
0ff83799 MM |
7640 | (define_insn "branch_zero_di" |
7641 | [(set (pc) | |
7642 | (if_then_else | |
7643 | (match_operator:DI 0 "cmp_op" | |
7644 | [(match_operand:DI 2 "se_register_operand" "d") | |
7645 | (const_int 0)]) | |
7646 | (label_ref (match_operand 1 "" "")) | |
7647 | (pc)))] | |
7648 | "!TARGET_MIPS16" | |
7649 | "* | |
7650 | { | |
7651 | return mips_output_conditional_branch (insn, | |
7652 | operands, | |
7653 | /*two_operands_p=*/0, | |
7654 | /*float_p=*/0, | |
7655 | /*inverted_p=*/0, | |
7656 | get_attr_length (insn)); | |
8ef30996 MM |
7657 | }" |
7658 | [(set_attr "type" "branch") | |
0ff83799 MM |
7659 | (set_attr "mode" "none")]) |
7660 | ||
7661 | (define_insn "branch_zero_di_inverted" | |
7662 | [(set (pc) | |
7663 | (if_then_else | |
7664 | (match_operator:DI 0 "cmp_op" | |
7665 | [(match_operand:DI 2 "se_register_operand" "d") | |
7666 | (const_int 0)]) | |
7667 | (pc) | |
7668 | (label_ref (match_operand 1 "" ""))))] | |
7669 | "!TARGET_MIPS16" | |
7670 | "* | |
7671 | { | |
7672 | return mips_output_conditional_branch (insn, | |
7673 | operands, | |
7674 | /*two_operands_p=*/0, | |
7675 | /*float_p=*/0, | |
7676 | /*inverted_p=*/1, | |
7677 | get_attr_length (insn)); | |
7678 | }" | |
7679 | [(set_attr "type" "branch") | |
7680 | (set_attr "mode" "none")]) | |
7681 | ||
7682 | ;; Conditional branch on equality comparision. | |
7683 | ||
7684 | (define_insn "branch_equality" | |
7685 | [(set (pc) | |
7686 | (if_then_else | |
7687 | (match_operator:SI 0 "equality_op" | |
7688 | [(match_operand:SI 2 "register_operand" "d") | |
7689 | (match_operand:SI 3 "register_operand" "d")]) | |
7690 | (label_ref (match_operand 1 "" "")) | |
7691 | (pc)))] | |
7692 | "!TARGET_MIPS16" | |
7693 | "* | |
7694 | { | |
7695 | return mips_output_conditional_branch (insn, | |
7696 | operands, | |
7697 | /*two_operands_p=*/1, | |
7698 | /*float_p=*/0, | |
7699 | /*inverted_p=*/0, | |
7700 | get_attr_length (insn)); | |
7701 | }" | |
7702 | [(set_attr "type" "branch") | |
7703 | (set_attr "mode" "none")]) | |
7704 | ||
7705 | (define_insn "branch_equality_di" | |
7706 | [(set (pc) | |
7707 | (if_then_else | |
7708 | (match_operator:DI 0 "equality_op" | |
7709 | [(match_operand:DI 2 "se_register_operand" "d") | |
7710 | (match_operand:DI 3 "se_register_operand" "d")]) | |
7711 | (label_ref (match_operand 1 "" "")) | |
7712 | (pc)))] | |
7713 | "!TARGET_MIPS16" | |
7714 | "* | |
7715 | { | |
7716 | return mips_output_conditional_branch (insn, | |
7717 | operands, | |
7718 | /*two_operands_p=*/1, | |
7719 | /*float_p=*/0, | |
7720 | /*inverted_p=*/0, | |
7721 | get_attr_length (insn)); | |
7722 | }" | |
7723 | [(set_attr "type" "branch") | |
7724 | (set_attr "mode" "none")]) | |
7725 | ||
7726 | (define_insn "branch_equality_inverted" | |
7727 | [(set (pc) | |
7728 | (if_then_else | |
7729 | (match_operator:SI 0 "equality_op" | |
7730 | [(match_operand:SI 2 "register_operand" "d") | |
7731 | (match_operand:SI 3 "register_operand" "d")]) | |
7732 | (pc) | |
7733 | (label_ref (match_operand 1 "" ""))))] | |
7734 | "!TARGET_MIPS16" | |
7735 | "* | |
7736 | { | |
7737 | return mips_output_conditional_branch (insn, | |
7738 | operands, | |
7739 | /*two_operands_p=*/1, | |
7740 | /*float_p=*/0, | |
7741 | /*inverted_p=*/1, | |
7742 | get_attr_length (insn)); | |
7743 | }" | |
7744 | [(set_attr "type" "branch") | |
7745 | (set_attr "mode" "none")]) | |
7746 | ||
7747 | (define_insn "branch_equality_di_inverted" | |
7748 | [(set (pc) | |
7749 | (if_then_else | |
7750 | (match_operator:DI 0 "equality_op" | |
7751 | [(match_operand:DI 2 "se_register_operand" "d") | |
7752 | (match_operand:DI 3 "se_register_operand" "d")]) | |
7753 | (pc) | |
7754 | (label_ref (match_operand 1 "" ""))))] | |
7755 | "!TARGET_MIPS16" | |
7756 | "* | |
7757 | { | |
7758 | return mips_output_conditional_branch (insn, | |
7759 | operands, | |
7760 | /*two_operands_p=*/1, | |
7761 | /*float_p=*/0, | |
7762 | /*inverted_p=*/1, | |
7763 | get_attr_length (insn)); | |
7764 | }" | |
7765 | [(set_attr "type" "branch") | |
7766 | (set_attr "mode" "none")]) | |
8ef30996 | 7767 | |
0ff83799 | 7768 | ;; MIPS16 branches |
8ef30996 | 7769 | |
2bcb2ab3 GK |
7770 | (define_insn "" |
7771 | [(set (pc) | |
7772 | (if_then_else (match_operator:SI 0 "equality_op" | |
7773 | [(match_operand:SI 1 "register_operand" "d,t") | |
7774 | (const_int 0)]) | |
7775 | (match_operand 2 "pc_or_label_operand" "") | |
7776 | (match_operand 3 "pc_or_label_operand" "")))] | |
7777 | "TARGET_MIPS16" | |
7778 | "* | |
7779 | { | |
7780 | if (operands[2] != pc_rtx) | |
7781 | { | |
7782 | if (which_alternative == 0) | |
7783 | return \"%*b%C0z\\t%1,%2\"; | |
7784 | else | |
7785 | return \"%*bt%C0z\\t%2\"; | |
7786 | } | |
7787 | else | |
7788 | { | |
7789 | if (which_alternative == 0) | |
7790 | return \"%*b%N0z\\t%1,%3\"; | |
7791 | else | |
7792 | return \"%*bt%N0z\\t%3\"; | |
7793 | } | |
7794 | }" | |
7795 | [(set_attr "type" "branch") | |
7796 | (set_attr "mode" "none") | |
0ff83799 | 7797 | (set_attr "length" "8")]) |
bb621ad7 | 7798 | |
2bcb2ab3 GK |
7799 | (define_insn "" |
7800 | [(set (pc) | |
7801 | (if_then_else (match_operator:DI 0 "equality_op" | |
7802 | [(match_operand:DI 1 "se_register_operand" "d,t") | |
7803 | (const_int 0)]) | |
7804 | (match_operand 2 "pc_or_label_operand" "") | |
7805 | (match_operand 3 "pc_or_label_operand" "")))] | |
7806 | "TARGET_MIPS16" | |
7807 | "* | |
7808 | { | |
7809 | if (operands[2] != pc_rtx) | |
7810 | { | |
7811 | if (which_alternative == 0) | |
7812 | return \"%*b%C0z\\t%1,%2\"; | |
7813 | else | |
7814 | return \"%*bt%C0z\\t%2\"; | |
7815 | } | |
7816 | else | |
7817 | { | |
7818 | if (which_alternative == 0) | |
7819 | return \"%*b%N0z\\t%1,%3\"; | |
7820 | else | |
7821 | return \"%*bt%N0z\\t%3\"; | |
7822 | } | |
7823 | }" | |
7824 | [(set_attr "type" "branch") | |
7825 | (set_attr "mode" "none") | |
0ff83799 | 7826 | (set_attr "length" "8")]) |
bb621ad7 | 7827 | |
8ef30996 MM |
7828 | (define_expand "beq" |
7829 | [(set (pc) | |
b8eb88d0 ILT |
7830 | (if_then_else (eq:CC (cc0) |
7831 | (const_int 0)) | |
8ef30996 MM |
7832 | (label_ref (match_operand 0 "" "")) |
7833 | (pc)))] | |
7834 | "" | |
7835 | " | |
7836 | { | |
7837 | if (operands[0]) /* avoid unused code warning */ | |
7838 | { | |
7839 | gen_conditional_branch (operands, EQ); | |
7840 | DONE; | |
7841 | } | |
7842 | }") | |
7843 | ||
7844 | (define_expand "bne" | |
7845 | [(set (pc) | |
b8eb88d0 ILT |
7846 | (if_then_else (ne:CC (cc0) |
7847 | (const_int 0)) | |
8ef30996 MM |
7848 | (label_ref (match_operand 0 "" "")) |
7849 | (pc)))] | |
7850 | "" | |
7851 | " | |
7852 | { | |
7853 | if (operands[0]) /* avoid unused code warning */ | |
7854 | { | |
7855 | gen_conditional_branch (operands, NE); | |
7856 | DONE; | |
7857 | } | |
7858 | }") | |
7859 | ||
7860 | (define_expand "bgt" | |
7861 | [(set (pc) | |
7862 | (if_then_else (gt:CC (cc0) | |
7863 | (const_int 0)) | |
7864 | (label_ref (match_operand 0 "" "")) | |
7865 | (pc)))] | |
7866 | "" | |
7867 | " | |
7868 | { | |
7869 | if (operands[0]) /* avoid unused code warning */ | |
7870 | { | |
7871 | gen_conditional_branch (operands, GT); | |
7872 | DONE; | |
7873 | } | |
7874 | }") | |
7875 | ||
7876 | (define_expand "bge" | |
7877 | [(set (pc) | |
7878 | (if_then_else (ge:CC (cc0) | |
7879 | (const_int 0)) | |
7880 | (label_ref (match_operand 0 "" "")) | |
7881 | (pc)))] | |
7882 | "" | |
7883 | " | |
7884 | { | |
7885 | if (operands[0]) /* avoid unused code warning */ | |
7886 | { | |
7887 | gen_conditional_branch (operands, GE); | |
7888 | DONE; | |
7889 | } | |
7890 | }") | |
7891 | ||
7892 | (define_expand "blt" | |
7893 | [(set (pc) | |
7894 | (if_then_else (lt:CC (cc0) | |
7895 | (const_int 0)) | |
7896 | (label_ref (match_operand 0 "" "")) | |
7897 | (pc)))] | |
7898 | "" | |
7899 | " | |
7900 | { | |
7901 | if (operands[0]) /* avoid unused code warning */ | |
7902 | { | |
7903 | gen_conditional_branch (operands, LT); | |
7904 | DONE; | |
7905 | } | |
7906 | }") | |
7907 | ||
7908 | (define_expand "ble" | |
7909 | [(set (pc) | |
7910 | (if_then_else (le:CC (cc0) | |
7911 | (const_int 0)) | |
7912 | (label_ref (match_operand 0 "" "")) | |
7913 | (pc)))] | |
7914 | "" | |
7915 | " | |
7916 | { | |
7917 | if (operands[0]) /* avoid unused code warning */ | |
7918 | { | |
7919 | gen_conditional_branch (operands, LE); | |
7920 | DONE; | |
7921 | } | |
7922 | }") | |
7923 | ||
7924 | (define_expand "bgtu" | |
7925 | [(set (pc) | |
7926 | (if_then_else (gtu:CC (cc0) | |
7927 | (const_int 0)) | |
7928 | (label_ref (match_operand 0 "" "")) | |
7929 | (pc)))] | |
7930 | "" | |
7931 | " | |
7932 | { | |
7933 | if (operands[0]) /* avoid unused code warning */ | |
7934 | { | |
7935 | gen_conditional_branch (operands, GTU); | |
7936 | DONE; | |
7937 | } | |
7938 | }") | |
7939 | ||
7940 | (define_expand "bgeu" | |
7941 | [(set (pc) | |
7942 | (if_then_else (geu:CC (cc0) | |
7943 | (const_int 0)) | |
7944 | (label_ref (match_operand 0 "" "")) | |
7945 | (pc)))] | |
7946 | "" | |
7947 | " | |
7948 | { | |
7949 | if (operands[0]) /* avoid unused code warning */ | |
7950 | { | |
7951 | gen_conditional_branch (operands, GEU); | |
7952 | DONE; | |
7953 | } | |
7954 | }") | |
7955 | ||
7956 | ||
7957 | (define_expand "bltu" | |
7958 | [(set (pc) | |
7959 | (if_then_else (ltu:CC (cc0) | |
7960 | (const_int 0)) | |
7961 | (label_ref (match_operand 0 "" "")) | |
7962 | (pc)))] | |
7963 | "" | |
7964 | " | |
7965 | { | |
7966 | if (operands[0]) /* avoid unused code warning */ | |
7967 | { | |
7968 | gen_conditional_branch (operands, LTU); | |
7969 | DONE; | |
7970 | } | |
7971 | }") | |
7972 | ||
7973 | (define_expand "bleu" | |
7974 | [(set (pc) | |
7975 | (if_then_else (leu:CC (cc0) | |
7976 | (const_int 0)) | |
7977 | (label_ref (match_operand 0 "" "")) | |
7978 | (pc)))] | |
7979 | "" | |
7980 | " | |
7981 | { | |
7982 | if (operands[0]) /* avoid unused code warning */ | |
7983 | { | |
7984 | gen_conditional_branch (operands, LEU); | |
7985 | DONE; | |
7986 | } | |
7987 | }") | |
7988 | ||
7989 | \f | |
7990 | ;; | |
7991 | ;; .................... | |
7992 | ;; | |
7993 | ;; SETTING A REGISTER FROM A COMPARISON | |
7994 | ;; | |
7995 | ;; .................... | |
7996 | ||
7997 | (define_expand "seq" | |
7998 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 MM |
7999 | (eq:SI (match_dup 1) |
8000 | (match_dup 2)))] | |
8ef30996 MM |
8001 | "" |
8002 | " | |
8003 | { | |
bb621ad7 | 8004 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8005 | FAIL; |
8006 | ||
8007 | /* set up operands from compare. */ | |
8008 | operands[1] = branch_cmp[0]; | |
8009 | operands[2] = branch_cmp[1]; | |
8010 | ||
2bcb2ab3 | 8011 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8012 | { |
8013 | gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0); | |
8014 | DONE; | |
8015 | } | |
8016 | ||
8ef30996 MM |
8017 | if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) |
8018 | operands[2] = force_reg (SImode, operands[2]); | |
8019 | ||
8020 | /* fall through and generate default code */ | |
8021 | }") | |
8022 | ||
34b650b3 MM |
8023 | |
8024 | (define_insn "seq_si_zero" | |
8025 | [(set (match_operand:SI 0 "register_operand" "=d") | |
8026 | (eq:SI (match_operand:SI 1 "register_operand" "d") | |
8027 | (const_int 0)))] | |
2bcb2ab3 | 8028 | "!TARGET_MIPS16" |
34b650b3 | 8029 | "sltu\\t%0,%1,1" |
bb621ad7 | 8030 | [(set_attr "type" "arith") |
0ff83799 | 8031 | (set_attr "mode" "SI")]) |
34b650b3 | 8032 | |
2bcb2ab3 GK |
8033 | (define_insn "" |
8034 | [(set (match_operand:SI 0 "register_operand" "=t") | |
8035 | (eq:SI (match_operand:SI 1 "register_operand" "d") | |
8036 | (const_int 0)))] | |
8037 | "TARGET_MIPS16" | |
8038 | "sltu\\t%1,1" | |
8039 | [(set_attr "type" "arith") | |
0ff83799 | 8040 | (set_attr "mode" "SI")]) |
2bcb2ab3 | 8041 | |
bb621ad7 JW |
8042 | (define_insn "seq_di_zero" |
8043 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 8044 | (eq:DI (match_operand:DI 1 "se_register_operand" "d") |
bb621ad7 | 8045 | (const_int 0)))] |
2bcb2ab3 | 8046 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
8047 | "sltu\\t%0,%1,1" |
8048 | [(set_attr "type" "arith") | |
0ff83799 | 8049 | (set_attr "mode" "DI")]) |
bb621ad7 | 8050 | |
2bcb2ab3 GK |
8051 | (define_insn "" |
8052 | [(set (match_operand:DI 0 "register_operand" "=t") | |
8053 | (eq:DI (match_operand:DI 1 "se_register_operand" "d") | |
8054 | (const_int 0)))] | |
8055 | "TARGET_64BIT && TARGET_MIPS16" | |
8056 | "sltu\\t%1,1" | |
8057 | [(set_attr "type" "arith") | |
0ff83799 | 8058 | (set_attr "mode" "DI")]) |
2bcb2ab3 | 8059 | |
34b650b3 MM |
8060 | (define_insn "seq_si" |
8061 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
8062 | (eq:SI (match_operand:SI 1 "register_operand" "%d,d") | |
8063 | (match_operand:SI 2 "uns_arith_operand" "d,K")))] | |
2bcb2ab3 | 8064 | "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
8ef30996 | 8065 | "@ |
8ef30996 | 8066 | xor\\t%0,%1,%2\;sltu\\t%0,%0,1 |
34b650b3 | 8067 | xori\\t%0,%1,%2\;sltu\\t%0,%0,1" |
bb621ad7 JW |
8068 | [(set_attr "type" "arith") |
8069 | (set_attr "mode" "SI") | |
0ff83799 | 8070 | (set_attr "length" "8")]) |
bb621ad7 JW |
8071 | |
8072 | (define_split | |
8073 | [(set (match_operand:SI 0 "register_operand" "") | |
8074 | (eq:SI (match_operand:SI 1 "register_operand" "") | |
8075 | (match_operand:SI 2 "uns_arith_operand" "")))] | |
2bcb2ab3 | 8076 | "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 |
bb621ad7 JW |
8077 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" |
8078 | [(set (match_dup 0) | |
8079 | (xor:SI (match_dup 1) | |
8080 | (match_dup 2))) | |
8081 | (set (match_dup 0) | |
8082 | (ltu:SI (match_dup 0) | |
8083 | (const_int 1)))] | |
8084 | "") | |
8085 | ||
8086 | (define_insn "seq_di" | |
8087 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
1908a152 ILT |
8088 | (eq:DI (match_operand:DI 1 "se_register_operand" "%d,d") |
8089 | (match_operand:DI 2 "se_uns_arith_operand" "d,K")))] | |
2bcb2ab3 | 8090 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
bb621ad7 JW |
8091 | "@ |
8092 | xor\\t%0,%1,%2\;sltu\\t%0,%0,1 | |
8093 | xori\\t%0,%1,%2\;sltu\\t%0,%0,1" | |
8094 | [(set_attr "type" "arith") | |
8095 | (set_attr "mode" "DI") | |
0ff83799 | 8096 | (set_attr "length" "8")]) |
8ef30996 MM |
8097 | |
8098 | (define_split | |
bb621ad7 | 8099 | [(set (match_operand:DI 0 "register_operand" "") |
1908a152 ILT |
8100 | (eq:DI (match_operand:DI 1 "se_register_operand" "") |
8101 | (match_operand:DI 2 "se_uns_arith_operand" "")))] | |
bb621ad7 | 8102 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE |
2bcb2ab3 | 8103 | && !TARGET_MIPS16 |
26b8e6e5 | 8104 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" |
8ef30996 | 8105 | [(set (match_dup 0) |
bb621ad7 | 8106 | (xor:DI (match_dup 1) |
8ef30996 MM |
8107 | (match_dup 2))) |
8108 | (set (match_dup 0) | |
bb621ad7 | 8109 | (ltu:DI (match_dup 0) |
8ef30996 MM |
8110 | (const_int 1)))] |
8111 | "") | |
8112 | ||
2bcb2ab3 GK |
8113 | ;; On the mips16 the default code is better than using sltu. |
8114 | ||
8ef30996 MM |
8115 | (define_expand "sne" |
8116 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 MM |
8117 | (ne:SI (match_dup 1) |
8118 | (match_dup 2)))] | |
2bcb2ab3 | 8119 | "!TARGET_MIPS16" |
8ef30996 MM |
8120 | " |
8121 | { | |
bb621ad7 | 8122 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8123 | FAIL; |
8124 | ||
8125 | /* set up operands from compare. */ | |
8126 | operands[1] = branch_cmp[0]; | |
8127 | operands[2] = branch_cmp[1]; | |
8128 | ||
bb621ad7 | 8129 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE) |
34b650b3 MM |
8130 | { |
8131 | gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0); | |
8132 | DONE; | |
8133 | } | |
8134 | ||
8ef30996 MM |
8135 | if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) |
8136 | operands[2] = force_reg (SImode, operands[2]); | |
8137 | ||
8138 | /* fall through and generate default code */ | |
8139 | }") | |
8140 | ||
34b650b3 MM |
8141 | (define_insn "sne_si_zero" |
8142 | [(set (match_operand:SI 0 "register_operand" "=d") | |
8143 | (ne:SI (match_operand:SI 1 "register_operand" "d") | |
8144 | (const_int 0)))] | |
2bcb2ab3 | 8145 | "!TARGET_MIPS16" |
34b650b3 | 8146 | "sltu\\t%0,%.,%1" |
bb621ad7 | 8147 | [(set_attr "type" "arith") |
0ff83799 | 8148 | (set_attr "mode" "SI")]) |
8ef30996 | 8149 | |
bb621ad7 JW |
8150 | (define_insn "sne_di_zero" |
8151 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 8152 | (ne:DI (match_operand:DI 1 "se_register_operand" "d") |
bb621ad7 | 8153 | (const_int 0)))] |
2bcb2ab3 | 8154 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
8155 | "sltu\\t%0,%.,%1" |
8156 | [(set_attr "type" "arith") | |
0ff83799 | 8157 | (set_attr "mode" "DI")]) |
bb621ad7 | 8158 | |
34b650b3 MM |
8159 | (define_insn "sne_si" |
8160 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
8161 | (ne:SI (match_operand:SI 1 "register_operand" "%d,d") | |
8162 | (match_operand:SI 2 "uns_arith_operand" "d,K")))] | |
2bcb2ab3 | 8163 | "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
34b650b3 MM |
8164 | "@ |
8165 | xor\\t%0,%1,%2\;sltu\\t%0,%.,%0 | |
8166 | xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0" | |
bb621ad7 | 8167 | [(set_attr "type" "arith") |
92b4cee1 | 8168 | (set_attr "mode" "SI") |
0ff83799 | 8169 | (set_attr "length" "8")]) |
8ef30996 MM |
8170 | |
8171 | (define_split | |
8172 | [(set (match_operand:SI 0 "register_operand" "") | |
34b650b3 MM |
8173 | (ne:SI (match_operand:SI 1 "register_operand" "") |
8174 | (match_operand:SI 2 "uns_arith_operand" "")))] | |
2bcb2ab3 | 8175 | "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 |
26b8e6e5 | 8176 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" |
8ef30996 MM |
8177 | [(set (match_dup 0) |
8178 | (xor:SI (match_dup 1) | |
8179 | (match_dup 2))) | |
8180 | (set (match_dup 0) | |
34b650b3 | 8181 | (gtu:SI (match_dup 0) |
8ef30996 MM |
8182 | (const_int 0)))] |
8183 | "") | |
8184 | ||
bb621ad7 JW |
8185 | (define_insn "sne_di" |
8186 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
1908a152 ILT |
8187 | (ne:DI (match_operand:DI 1 "se_register_operand" "%d,d") |
8188 | (match_operand:DI 2 "se_uns_arith_operand" "d,K")))] | |
2bcb2ab3 | 8189 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
bb621ad7 JW |
8190 | "@ |
8191 | xor\\t%0,%1,%2\;sltu\\t%0,%.,%0 | |
8192 | xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0" | |
8193 | [(set_attr "type" "arith") | |
8194 | (set_attr "mode" "DI") | |
0ff83799 | 8195 | (set_attr "length" "8")]) |
bb621ad7 JW |
8196 | |
8197 | (define_split | |
8198 | [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 ILT |
8199 | (ne:DI (match_operand:DI 1 "se_register_operand" "") |
8200 | (match_operand:DI 2 "se_uns_arith_operand" "")))] | |
bb621ad7 | 8201 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE |
2bcb2ab3 | 8202 | && !TARGET_MIPS16 |
bb621ad7 JW |
8203 | && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" |
8204 | [(set (match_dup 0) | |
8205 | (xor:DI (match_dup 1) | |
8206 | (match_dup 2))) | |
8207 | (set (match_dup 0) | |
8208 | (gtu:DI (match_dup 0) | |
8209 | (const_int 0)))] | |
8210 | "") | |
8211 | ||
8ef30996 MM |
8212 | (define_expand "sgt" |
8213 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8214 | (gt:SI (match_dup 1) |
8ef30996 MM |
8215 | (match_dup 2)))] |
8216 | "" | |
8217 | " | |
8218 | { | |
bb621ad7 | 8219 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8220 | FAIL; |
8221 | ||
8222 | /* set up operands from compare. */ | |
8223 | operands[1] = branch_cmp[0]; | |
8224 | operands[2] = branch_cmp[1]; | |
8225 | ||
2bcb2ab3 | 8226 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8227 | { |
8228 | gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0); | |
8229 | DONE; | |
8230 | } | |
8231 | ||
8ef30996 MM |
8232 | if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) |
8233 | operands[2] = force_reg (SImode, operands[2]); | |
8234 | ||
8235 | /* fall through and generate default code */ | |
8236 | }") | |
8237 | ||
8238 | (define_insn "sgt_si" | |
8239 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8240 | (gt:SI (match_operand:SI 1 "register_operand" "d") |
8ef30996 | 8241 | (match_operand:SI 2 "reg_or_0_operand" "dJ")))] |
2bcb2ab3 | 8242 | "!TARGET_MIPS16" |
8ef30996 | 8243 | "slt\\t%0,%z2,%1" |
bb621ad7 | 8244 | [(set_attr "type" "arith") |
0ff83799 | 8245 | (set_attr "mode" "SI")]) |
8ef30996 | 8246 | |
2bcb2ab3 GK |
8247 | (define_insn "" |
8248 | [(set (match_operand:SI 0 "register_operand" "=t") | |
8249 | (gt:SI (match_operand:SI 1 "register_operand" "d") | |
8250 | (match_operand:SI 2 "register_operand" "d")))] | |
8251 | "TARGET_MIPS16" | |
8252 | "slt\\t%2,%1" | |
8253 | [(set_attr "type" "arith") | |
0ff83799 | 8254 | (set_attr "mode" "SI")]) |
2bcb2ab3 | 8255 | |
bb621ad7 JW |
8256 | (define_insn "sgt_di" |
8257 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
8258 | (gt:DI (match_operand:DI 1 "se_register_operand" "d") |
8259 | (match_operand:DI 2 "se_reg_or_0_operand" "dJ")))] | |
2bcb2ab3 | 8260 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
8261 | "slt\\t%0,%z2,%1" |
8262 | [(set_attr "type" "arith") | |
0ff83799 | 8263 | (set_attr "mode" "DI")]) |
bb621ad7 | 8264 | |
2bcb2ab3 GK |
8265 | (define_insn "" |
8266 | [(set (match_operand:DI 0 "register_operand" "=d") | |
8267 | (gt:DI (match_operand:DI 1 "se_register_operand" "d") | |
8268 | (match_operand:DI 2 "se_register_operand" "d")))] | |
8269 | "TARGET_64BIT && TARGET_MIPS16" | |
8270 | "slt\\t%2,%1" | |
8271 | [(set_attr "type" "arith") | |
0ff83799 | 8272 | (set_attr "mode" "DI")]) |
2bcb2ab3 | 8273 | |
8ef30996 MM |
8274 | (define_expand "sge" |
8275 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8276 | (ge:SI (match_dup 1) |
8ef30996 MM |
8277 | (match_dup 2)))] |
8278 | "" | |
8279 | " | |
8280 | { | |
bb621ad7 | 8281 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8282 | FAIL; |
8283 | ||
8284 | /* set up operands from compare. */ | |
8285 | operands[1] = branch_cmp[0]; | |
8286 | operands[2] = branch_cmp[1]; | |
8287 | ||
2bcb2ab3 | 8288 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8289 | { |
8290 | gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0); | |
8291 | DONE; | |
8292 | } | |
8293 | ||
8ef30996 MM |
8294 | /* fall through and generate default code */ |
8295 | }") | |
8296 | ||
8297 | (define_insn "sge_si" | |
8298 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8299 | (ge:SI (match_operand:SI 1 "register_operand" "d") |
8ef30996 | 8300 | (match_operand:SI 2 "arith_operand" "dI")))] |
2bcb2ab3 | 8301 | "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
8ef30996 | 8302 | "slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001" |
bb621ad7 | 8303 | [(set_attr "type" "arith") |
8ef30996 | 8304 | (set_attr "mode" "SI") |
0ff83799 | 8305 | (set_attr "length" "8")]) |
8ef30996 MM |
8306 | |
8307 | (define_split | |
8308 | [(set (match_operand:SI 0 "register_operand" "") | |
34b650b3 | 8309 | (ge:SI (match_operand:SI 1 "register_operand" "") |
8ef30996 | 8310 | (match_operand:SI 2 "arith_operand" "")))] |
2bcb2ab3 | 8311 | "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16" |
8ef30996 | 8312 | [(set (match_dup 0) |
34b650b3 | 8313 | (lt:SI (match_dup 1) |
8ef30996 MM |
8314 | (match_dup 2))) |
8315 | (set (match_dup 0) | |
8316 | (xor:SI (match_dup 0) | |
8317 | (const_int 1)))] | |
8318 | "") | |
8319 | ||
bb621ad7 JW |
8320 | (define_insn "sge_di" |
8321 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
8322 | (ge:DI (match_operand:DI 1 "se_register_operand" "d") |
8323 | (match_operand:DI 2 "se_arith_operand" "dI")))] | |
2bcb2ab3 | 8324 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
bb621ad7 JW |
8325 | "slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001" |
8326 | [(set_attr "type" "arith") | |
8327 | (set_attr "mode" "DI") | |
0ff83799 | 8328 | (set_attr "length" "8")]) |
bb621ad7 JW |
8329 | |
8330 | (define_split | |
8331 | [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 ILT |
8332 | (ge:DI (match_operand:DI 1 "se_register_operand" "") |
8333 | (match_operand:DI 2 "se_arith_operand" "")))] | |
2bcb2ab3 GK |
8334 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE |
8335 | && !TARGET_MIPS16" | |
bb621ad7 JW |
8336 | [(set (match_dup 0) |
8337 | (lt:DI (match_dup 1) | |
8338 | (match_dup 2))) | |
8339 | (set (match_dup 0) | |
8340 | (xor:DI (match_dup 0) | |
8341 | (const_int 1)))] | |
8342 | "") | |
8343 | ||
8ef30996 MM |
8344 | (define_expand "slt" |
8345 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8346 | (lt:SI (match_dup 1) |
8ef30996 MM |
8347 | (match_dup 2)))] |
8348 | "" | |
8349 | " | |
8350 | { | |
bb621ad7 | 8351 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8352 | FAIL; |
8353 | ||
8354 | /* set up operands from compare. */ | |
8355 | operands[1] = branch_cmp[0]; | |
8356 | operands[2] = branch_cmp[1]; | |
8357 | ||
2bcb2ab3 | 8358 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8359 | { |
8360 | gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0); | |
8361 | DONE; | |
8362 | } | |
8363 | ||
8ef30996 MM |
8364 | /* fall through and generate default code */ |
8365 | }") | |
8366 | ||
8367 | (define_insn "slt_si" | |
8368 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8369 | (lt:SI (match_operand:SI 1 "register_operand" "d") |
8ef30996 | 8370 | (match_operand:SI 2 "arith_operand" "dI")))] |
2bcb2ab3 | 8371 | "!TARGET_MIPS16" |
8ef30996 | 8372 | "slt\\t%0,%1,%2" |
bb621ad7 | 8373 | [(set_attr "type" "arith") |
0ff83799 | 8374 | (set_attr "mode" "SI")]) |
8ef30996 | 8375 | |
2bcb2ab3 GK |
8376 | (define_insn "" |
8377 | [(set (match_operand:SI 0 "register_operand" "=t,t") | |
8378 | (lt:SI (match_operand:SI 1 "register_operand" "d,d") | |
8379 | (match_operand:SI 2 "arith_operand" "d,I")))] | |
8380 | "TARGET_MIPS16" | |
8381 | "slt\\t%1,%2" | |
8382 | [(set_attr "type" "arith") | |
8383 | (set_attr "mode" "SI") | |
8384 | (set_attr_alternative "length" | |
0ff83799 | 8385 | [(const_int 4) |
2bcb2ab3 | 8386 | (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") |
0ff83799 MM |
8387 | (const_int 4) |
8388 | (const_int 8))])]) | |
2bcb2ab3 | 8389 | |
bb621ad7 JW |
8390 | (define_insn "slt_di" |
8391 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
8392 | (lt:DI (match_operand:DI 1 "se_register_operand" "d") |
8393 | (match_operand:DI 2 "se_arith_operand" "dI")))] | |
2bcb2ab3 | 8394 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
8395 | "slt\\t%0,%1,%2" |
8396 | [(set_attr "type" "arith") | |
0ff83799 | 8397 | (set_attr "mode" "DI")]) |
bb621ad7 | 8398 | |
2bcb2ab3 GK |
8399 | (define_insn "" |
8400 | [(set (match_operand:DI 0 "register_operand" "=t,t") | |
8401 | (lt:DI (match_operand:DI 1 "se_register_operand" "d,d") | |
8402 | (match_operand:DI 2 "se_arith_operand" "d,I")))] | |
8403 | "TARGET_64BIT && TARGET_MIPS16" | |
8404 | "slt\\t%1,%2" | |
8405 | [(set_attr "type" "arith") | |
8406 | (set_attr "mode" "DI") | |
8407 | (set_attr_alternative "length" | |
0ff83799 | 8408 | [(const_int 4) |
2bcb2ab3 | 8409 | (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") |
0ff83799 MM |
8410 | (const_int 4) |
8411 | (const_int 8))])]) | |
2bcb2ab3 | 8412 | |
8ef30996 MM |
8413 | (define_expand "sle" |
8414 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8415 | (le:SI (match_dup 1) |
8ef30996 MM |
8416 | (match_dup 2)))] |
8417 | "" | |
8418 | " | |
8419 | { | |
bb621ad7 | 8420 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8421 | FAIL; |
8422 | ||
8423 | /* set up operands from compare. */ | |
8424 | operands[1] = branch_cmp[0]; | |
8425 | operands[2] = branch_cmp[1]; | |
8426 | ||
2bcb2ab3 | 8427 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8428 | { |
8429 | gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0); | |
8430 | DONE; | |
8431 | } | |
8432 | ||
8ef30996 MM |
8433 | if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) |
8434 | operands[2] = force_reg (SImode, operands[2]); | |
8435 | ||
8436 | /* fall through and generate default code */ | |
8437 | }") | |
8438 | ||
34b650b3 MM |
8439 | (define_insn "sle_si_const" |
8440 | [(set (match_operand:SI 0 "register_operand" "=d") | |
8441 | (le:SI (match_operand:SI 1 "register_operand" "d") | |
8442 | (match_operand:SI 2 "small_int" "I")))] | |
2bcb2ab3 | 8443 | "!TARGET_MIPS16 && INTVAL (operands[2]) < 32767" |
34b650b3 MM |
8444 | "* |
8445 | { | |
95936d18 | 8446 | operands[2] = GEN_INT (INTVAL (operands[2])+1); |
34b650b3 MM |
8447 | return \"slt\\t%0,%1,%2\"; |
8448 | }" | |
bb621ad7 | 8449 | [(set_attr "type" "arith") |
0ff83799 | 8450 | (set_attr "mode" "SI")]) |
34b650b3 | 8451 | |
2bcb2ab3 GK |
8452 | (define_insn "" |
8453 | [(set (match_operand:SI 0 "register_operand" "=t") | |
8454 | (le:SI (match_operand:SI 1 "register_operand" "d") | |
8455 | (match_operand:SI 2 "small_int" "I")))] | |
8456 | "TARGET_MIPS16 && INTVAL (operands[2]) < 32767" | |
8457 | "* | |
8458 | { | |
95936d18 | 8459 | operands[2] = GEN_INT (INTVAL (operands[2])+1); |
2bcb2ab3 GK |
8460 | return \"slt\\t%1,%2\"; |
8461 | }" | |
8462 | [(set_attr "type" "arith") | |
8463 | (set_attr "mode" "SI") | |
8464 | (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") | |
0ff83799 MM |
8465 | (const_int 4) |
8466 | (const_int 8)))]) | |
2bcb2ab3 | 8467 | |
bb621ad7 JW |
8468 | (define_insn "sle_di_const" |
8469 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 8470 | (le:DI (match_operand:DI 1 "se_register_operand" "d") |
bb621ad7 | 8471 | (match_operand:DI 2 "small_int" "I")))] |
2bcb2ab3 | 8472 | "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) < 32767" |
bb621ad7 JW |
8473 | "* |
8474 | { | |
95936d18 | 8475 | operands[2] = GEN_INT (INTVAL (operands[2])+1); |
bb621ad7 JW |
8476 | return \"slt\\t%0,%1,%2\"; |
8477 | }" | |
8478 | [(set_attr "type" "arith") | |
0ff83799 | 8479 | (set_attr "mode" "DI")]) |
bb621ad7 | 8480 | |
2bcb2ab3 GK |
8481 | (define_insn "" |
8482 | [(set (match_operand:DI 0 "register_operand" "=t") | |
8483 | (le:DI (match_operand:DI 1 "se_register_operand" "d") | |
8484 | (match_operand:DI 2 "small_int" "I")))] | |
8485 | "TARGET_64BIT && TARGET_MIPS16 && INTVAL (operands[2]) < 32767" | |
8486 | "* | |
8487 | { | |
95936d18 | 8488 | operands[2] = GEN_INT (INTVAL (operands[2])+1); |
2bcb2ab3 GK |
8489 | return \"slt\\t%1,%2\"; |
8490 | }" | |
8491 | [(set_attr "type" "arith") | |
8492 | (set_attr "mode" "DI") | |
8493 | (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") | |
0ff83799 MM |
8494 | (const_int 4) |
8495 | (const_int 8)))]) | |
2bcb2ab3 | 8496 | |
34b650b3 MM |
8497 | (define_insn "sle_si_reg" |
8498 | [(set (match_operand:SI 0 "register_operand" "=d") | |
8499 | (le:SI (match_operand:SI 1 "register_operand" "d") | |
8500 | (match_operand:SI 2 "register_operand" "d")))] | |
2bcb2ab3 | 8501 | "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
34b650b3 | 8502 | "slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" |
bb621ad7 | 8503 | [(set_attr "type" "arith") |
34b650b3 | 8504 | (set_attr "mode" "SI") |
0ff83799 | 8505 | (set_attr "length" "8")]) |
8ef30996 MM |
8506 | |
8507 | (define_split | |
8508 | [(set (match_operand:SI 0 "register_operand" "") | |
34b650b3 | 8509 | (le:SI (match_operand:SI 1 "register_operand" "") |
8ef30996 | 8510 | (match_operand:SI 2 "register_operand" "")))] |
2bcb2ab3 | 8511 | "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16" |
8ef30996 | 8512 | [(set (match_dup 0) |
34b650b3 | 8513 | (lt:SI (match_dup 2) |
8ef30996 MM |
8514 | (match_dup 1))) |
8515 | (set (match_dup 0) | |
8516 | (xor:SI (match_dup 0) | |
8517 | (const_int 1)))] | |
8518 | "") | |
8519 | ||
bb621ad7 JW |
8520 | (define_insn "sle_di_reg" |
8521 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
8522 | (le:DI (match_operand:DI 1 "se_register_operand" "d") |
8523 | (match_operand:DI 2 "se_register_operand" "d")))] | |
2bcb2ab3 | 8524 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
bb621ad7 JW |
8525 | "slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" |
8526 | [(set_attr "type" "arith") | |
8527 | (set_attr "mode" "DI") | |
0ff83799 | 8528 | (set_attr "length" "8")]) |
bb621ad7 JW |
8529 | |
8530 | (define_split | |
8531 | [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 ILT |
8532 | (le:DI (match_operand:DI 1 "se_register_operand" "") |
8533 | (match_operand:DI 2 "se_register_operand" "")))] | |
2bcb2ab3 GK |
8534 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE |
8535 | && !TARGET_MIPS16" | |
bb621ad7 JW |
8536 | [(set (match_dup 0) |
8537 | (lt:DI (match_dup 2) | |
8538 | (match_dup 1))) | |
8539 | (set (match_dup 0) | |
8540 | (xor:DI (match_dup 0) | |
8541 | (const_int 1)))] | |
8542 | "") | |
8543 | ||
8ef30996 MM |
8544 | (define_expand "sgtu" |
8545 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8546 | (gtu:SI (match_dup 1) |
8ef30996 MM |
8547 | (match_dup 2)))] |
8548 | "" | |
8549 | " | |
8550 | { | |
bb621ad7 | 8551 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8552 | FAIL; |
8553 | ||
8554 | /* set up operands from compare. */ | |
8555 | operands[1] = branch_cmp[0]; | |
8556 | operands[2] = branch_cmp[1]; | |
8557 | ||
2bcb2ab3 | 8558 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8559 | { |
8560 | gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0); | |
8561 | DONE; | |
8562 | } | |
8563 | ||
8ef30996 MM |
8564 | if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) |
8565 | operands[2] = force_reg (SImode, operands[2]); | |
8566 | ||
8567 | /* fall through and generate default code */ | |
8568 | }") | |
8569 | ||
8570 | (define_insn "sgtu_si" | |
8571 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8572 | (gtu:SI (match_operand:SI 1 "register_operand" "d") |
8ef30996 MM |
8573 | (match_operand:SI 2 "reg_or_0_operand" "dJ")))] |
8574 | "" | |
8575 | "sltu\\t%0,%z2,%1" | |
bb621ad7 | 8576 | [(set_attr "type" "arith") |
0ff83799 | 8577 | (set_attr "mode" "SI")]) |
8ef30996 | 8578 | |
2bcb2ab3 GK |
8579 | (define_insn "" |
8580 | [(set (match_operand:SI 0 "register_operand" "=t") | |
8581 | (gtu:SI (match_operand:SI 1 "register_operand" "d") | |
8582 | (match_operand:SI 2 "register_operand" "d")))] | |
8583 | "" | |
8584 | "sltu\\t%2,%1" | |
8585 | [(set_attr "type" "arith") | |
0ff83799 | 8586 | (set_attr "mode" "SI")]) |
2bcb2ab3 | 8587 | |
bb621ad7 JW |
8588 | (define_insn "sgtu_di" |
8589 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
8590 | (gtu:DI (match_operand:DI 1 "se_register_operand" "d") |
8591 | (match_operand:DI 2 "se_reg_or_0_operand" "dJ")))] | |
bb621ad7 JW |
8592 | "TARGET_64BIT" |
8593 | "sltu\\t%0,%z2,%1" | |
8594 | [(set_attr "type" "arith") | |
0ff83799 | 8595 | (set_attr "mode" "DI")]) |
bb621ad7 | 8596 | |
2bcb2ab3 GK |
8597 | (define_insn "" |
8598 | [(set (match_operand:DI 0 "register_operand" "=t") | |
8599 | (gtu:DI (match_operand:DI 1 "se_register_operand" "d") | |
8600 | (match_operand:DI 2 "se_register_operand" "d")))] | |
8601 | "TARGET_64BIT" | |
8602 | "sltu\\t%2,%1" | |
8603 | [(set_attr "type" "arith") | |
0ff83799 | 8604 | (set_attr "mode" "DI")]) |
2bcb2ab3 | 8605 | |
8ef30996 MM |
8606 | (define_expand "sgeu" |
8607 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8608 | (geu:SI (match_dup 1) |
8ef30996 MM |
8609 | (match_dup 2)))] |
8610 | "" | |
8611 | " | |
8612 | { | |
bb621ad7 | 8613 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8614 | FAIL; |
8615 | ||
8616 | /* set up operands from compare. */ | |
8617 | operands[1] = branch_cmp[0]; | |
8618 | operands[2] = branch_cmp[1]; | |
8619 | ||
2bcb2ab3 | 8620 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8621 | { |
8622 | gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0); | |
8623 | DONE; | |
8624 | } | |
8625 | ||
8ef30996 MM |
8626 | /* fall through and generate default code */ |
8627 | }") | |
8628 | ||
8629 | (define_insn "sgeu_si" | |
8630 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8631 | (geu:SI (match_operand:SI 1 "register_operand" "d") |
8ef30996 | 8632 | (match_operand:SI 2 "arith_operand" "dI")))] |
2bcb2ab3 | 8633 | "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
8ef30996 | 8634 | "sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001" |
bb621ad7 | 8635 | [(set_attr "type" "arith") |
8ef30996 | 8636 | (set_attr "mode" "SI") |
0ff83799 | 8637 | (set_attr "length" "8")]) |
8ef30996 MM |
8638 | |
8639 | (define_split | |
8640 | [(set (match_operand:SI 0 "register_operand" "") | |
34b650b3 | 8641 | (geu:SI (match_operand:SI 1 "register_operand" "") |
8ef30996 | 8642 | (match_operand:SI 2 "arith_operand" "")))] |
2bcb2ab3 | 8643 | "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16" |
8ef30996 | 8644 | [(set (match_dup 0) |
34b650b3 | 8645 | (ltu:SI (match_dup 1) |
8ef30996 MM |
8646 | (match_dup 2))) |
8647 | (set (match_dup 0) | |
8648 | (xor:SI (match_dup 0) | |
8649 | (const_int 1)))] | |
8650 | "") | |
8651 | ||
bb621ad7 JW |
8652 | (define_insn "sgeu_di" |
8653 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
8654 | (geu:DI (match_operand:DI 1 "se_register_operand" "d") |
8655 | (match_operand:DI 2 "se_arith_operand" "dI")))] | |
2bcb2ab3 | 8656 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
bb621ad7 JW |
8657 | "sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001" |
8658 | [(set_attr "type" "arith") | |
8659 | (set_attr "mode" "DI") | |
0ff83799 | 8660 | (set_attr "length" "8")]) |
bb621ad7 JW |
8661 | |
8662 | (define_split | |
8663 | [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 ILT |
8664 | (geu:DI (match_operand:DI 1 "se_register_operand" "") |
8665 | (match_operand:DI 2 "se_arith_operand" "")))] | |
2bcb2ab3 GK |
8666 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE |
8667 | && !TARGET_MIPS16" | |
bb621ad7 JW |
8668 | [(set (match_dup 0) |
8669 | (ltu:DI (match_dup 1) | |
8670 | (match_dup 2))) | |
8671 | (set (match_dup 0) | |
8672 | (xor:DI (match_dup 0) | |
8673 | (const_int 1)))] | |
8674 | "") | |
8675 | ||
8ef30996 MM |
8676 | (define_expand "sltu" |
8677 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8678 | (ltu:SI (match_dup 1) |
8ef30996 MM |
8679 | (match_dup 2)))] |
8680 | "" | |
8681 | " | |
8682 | { | |
bb621ad7 | 8683 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8684 | FAIL; |
8685 | ||
8686 | /* set up operands from compare. */ | |
8687 | operands[1] = branch_cmp[0]; | |
8688 | operands[2] = branch_cmp[1]; | |
8689 | ||
2bcb2ab3 | 8690 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8691 | { |
8692 | gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0); | |
8693 | DONE; | |
8694 | } | |
8695 | ||
8ef30996 MM |
8696 | /* fall through and generate default code */ |
8697 | }") | |
8698 | ||
8699 | (define_insn "sltu_si" | |
8700 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8701 | (ltu:SI (match_operand:SI 1 "register_operand" "d") |
8ef30996 | 8702 | (match_operand:SI 2 "arith_operand" "dI")))] |
2bcb2ab3 | 8703 | "!TARGET_MIPS16" |
8ef30996 | 8704 | "sltu\\t%0,%1,%2" |
bb621ad7 | 8705 | [(set_attr "type" "arith") |
0ff83799 | 8706 | (set_attr "mode" "SI")]) |
8ef30996 | 8707 | |
2bcb2ab3 GK |
8708 | (define_insn "" |
8709 | [(set (match_operand:SI 0 "register_operand" "=t,t") | |
8710 | (ltu:SI (match_operand:SI 1 "register_operand" "d,d") | |
8711 | (match_operand:SI 2 "arith_operand" "d,I")))] | |
8712 | "TARGET_MIPS16" | |
8713 | "sltu\\t%1,%2" | |
8714 | [(set_attr "type" "arith") | |
8715 | (set_attr "mode" "SI") | |
8716 | (set_attr_alternative "length" | |
0ff83799 | 8717 | [(const_int 4) |
2bcb2ab3 | 8718 | (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") |
0ff83799 MM |
8719 | (const_int 4) |
8720 | (const_int 8))])]) | |
2bcb2ab3 | 8721 | |
bb621ad7 JW |
8722 | (define_insn "sltu_di" |
8723 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
8724 | (ltu:DI (match_operand:DI 1 "se_register_operand" "d") |
8725 | (match_operand:DI 2 "se_arith_operand" "dI")))] | |
2bcb2ab3 | 8726 | "TARGET_64BIT && !TARGET_MIPS16" |
bb621ad7 JW |
8727 | "sltu\\t%0,%1,%2" |
8728 | [(set_attr "type" "arith") | |
0ff83799 | 8729 | (set_attr "mode" "DI")]) |
bb621ad7 | 8730 | |
2bcb2ab3 GK |
8731 | (define_insn "" |
8732 | [(set (match_operand:DI 0 "register_operand" "=t,t") | |
8733 | (ltu:DI (match_operand:DI 1 "se_register_operand" "d,d") | |
8734 | (match_operand:DI 2 "se_arith_operand" "d,I")))] | |
8735 | "TARGET_64BIT && TARGET_MIPS16" | |
8736 | "sltu\\t%1,%2" | |
8737 | [(set_attr "type" "arith") | |
8738 | (set_attr "mode" "DI") | |
8739 | (set_attr_alternative "length" | |
0ff83799 | 8740 | [(const_int 4) |
2bcb2ab3 | 8741 | (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") |
0ff83799 MM |
8742 | (const_int 4) |
8743 | (const_int 8))])]) | |
2bcb2ab3 | 8744 | |
8ef30996 MM |
8745 | (define_expand "sleu" |
8746 | [(set (match_operand:SI 0 "register_operand" "=d") | |
34b650b3 | 8747 | (leu:SI (match_dup 1) |
8ef30996 MM |
8748 | (match_dup 2)))] |
8749 | "" | |
8750 | " | |
8751 | { | |
bb621ad7 | 8752 | if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) |
8ef30996 MM |
8753 | FAIL; |
8754 | ||
8755 | /* set up operands from compare. */ | |
8756 | operands[1] = branch_cmp[0]; | |
8757 | operands[2] = branch_cmp[1]; | |
8758 | ||
2bcb2ab3 | 8759 | if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) |
34b650b3 MM |
8760 | { |
8761 | gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0); | |
8762 | DONE; | |
8763 | } | |
8764 | ||
8ef30996 MM |
8765 | if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) |
8766 | operands[2] = force_reg (SImode, operands[2]); | |
8767 | ||
8768 | /* fall through and generate default code */ | |
8769 | }") | |
8770 | ||
34b650b3 MM |
8771 | (define_insn "sleu_si_const" |
8772 | [(set (match_operand:SI 0 "register_operand" "=d") | |
8773 | (leu:SI (match_operand:SI 1 "register_operand" "d") | |
8774 | (match_operand:SI 2 "small_int" "I")))] | |
2bcb2ab3 | 8775 | "!TARGET_MIPS16 && INTVAL (operands[2]) < 32767" |
34b650b3 MM |
8776 | "* |
8777 | { | |
c5c76735 | 8778 | operands[2] = GEN_INT (INTVAL (operands[2]) + 1); |
34b650b3 MM |
8779 | return \"sltu\\t%0,%1,%2\"; |
8780 | }" | |
bb621ad7 | 8781 | [(set_attr "type" "arith") |
0ff83799 | 8782 | (set_attr "mode" "SI")]) |
34b650b3 | 8783 | |
2bcb2ab3 GK |
8784 | (define_insn "" |
8785 | [(set (match_operand:SI 0 "register_operand" "=t") | |
8786 | (leu:SI (match_operand:SI 1 "register_operand" "d") | |
8787 | (match_operand:SI 2 "small_int" "I")))] | |
8788 | "TARGET_MIPS16 && INTVAL (operands[2]) < 32767" | |
8789 | "* | |
8790 | { | |
95936d18 | 8791 | operands[2] = GEN_INT (INTVAL (operands[2])+1); |
2bcb2ab3 GK |
8792 | return \"sltu\\t%1,%2\"; |
8793 | }" | |
8794 | [(set_attr "type" "arith") | |
8795 | (set_attr "mode" "SI") | |
8796 | (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") | |
0ff83799 MM |
8797 | (const_int 4) |
8798 | (const_int 8)))]) | |
2bcb2ab3 | 8799 | |
bb621ad7 JW |
8800 | (define_insn "sleu_di_const" |
8801 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 | 8802 | (leu:DI (match_operand:DI 1 "se_register_operand" "d") |
bb621ad7 | 8803 | (match_operand:DI 2 "small_int" "I")))] |
2bcb2ab3 | 8804 | "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) < 32767" |
bb621ad7 JW |
8805 | "* |
8806 | { | |
c5c76735 | 8807 | operands[2] = GEN_INT (INTVAL (operands[2]) + 1); |
bb621ad7 JW |
8808 | return \"sltu\\t%0,%1,%2\"; |
8809 | }" | |
8810 | [(set_attr "type" "arith") | |
0ff83799 | 8811 | (set_attr "mode" "DI")]) |
bb621ad7 | 8812 | |
2bcb2ab3 GK |
8813 | (define_insn "" |
8814 | [(set (match_operand:DI 0 "register_operand" "=t") | |
8815 | (leu:DI (match_operand:DI 1 "se_register_operand" "d") | |
8816 | (match_operand:DI 2 "small_int" "I")))] | |
8817 | "TARGET_64BIT && TARGET_MIPS16 && INTVAL (operands[2]) < 32767" | |
8818 | "* | |
8819 | { | |
95936d18 | 8820 | operands[2] = GEN_INT (INTVAL (operands[2])+1); |
2bcb2ab3 GK |
8821 | return \"sltu\\t%1,%2\"; |
8822 | }" | |
8823 | [(set_attr "type" "arith") | |
8824 | (set_attr "mode" "DI") | |
8825 | (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") | |
0ff83799 MM |
8826 | (const_int 4) |
8827 | (const_int 8)))]) | |
2bcb2ab3 | 8828 | |
34b650b3 MM |
8829 | (define_insn "sleu_si_reg" |
8830 | [(set (match_operand:SI 0 "register_operand" "=d") | |
8831 | (leu:SI (match_operand:SI 1 "register_operand" "d") | |
8832 | (match_operand:SI 2 "register_operand" "d")))] | |
2bcb2ab3 | 8833 | "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
34b650b3 | 8834 | "sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" |
bb621ad7 | 8835 | [(set_attr "type" "arith") |
34b650b3 | 8836 | (set_attr "mode" "SI") |
0ff83799 | 8837 | (set_attr "length" "8")]) |
8ef30996 MM |
8838 | |
8839 | (define_split | |
8840 | [(set (match_operand:SI 0 "register_operand" "") | |
34b650b3 | 8841 | (leu:SI (match_operand:SI 1 "register_operand" "") |
8ef30996 | 8842 | (match_operand:SI 2 "register_operand" "")))] |
2bcb2ab3 | 8843 | "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16" |
8ef30996 | 8844 | [(set (match_dup 0) |
34b650b3 | 8845 | (ltu:SI (match_dup 2) |
8ef30996 MM |
8846 | (match_dup 1))) |
8847 | (set (match_dup 0) | |
8848 | (xor:SI (match_dup 0) | |
8849 | (const_int 1)))] | |
8850 | "") | |
8851 | ||
bb621ad7 JW |
8852 | (define_insn "sleu_di_reg" |
8853 | [(set (match_operand:DI 0 "register_operand" "=d") | |
1908a152 ILT |
8854 | (leu:DI (match_operand:DI 1 "se_register_operand" "d") |
8855 | (match_operand:DI 2 "se_register_operand" "d")))] | |
2bcb2ab3 | 8856 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" |
bb621ad7 JW |
8857 | "sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" |
8858 | [(set_attr "type" "arith") | |
8859 | (set_attr "mode" "DI") | |
0ff83799 | 8860 | (set_attr "length" "8")]) |
bb621ad7 JW |
8861 | |
8862 | (define_split | |
8863 | [(set (match_operand:DI 0 "register_operand" "") | |
1908a152 ILT |
8864 | (leu:DI (match_operand:DI 1 "se_register_operand" "") |
8865 | (match_operand:DI 2 "se_register_operand" "")))] | |
2bcb2ab3 GK |
8866 | "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE |
8867 | && !TARGET_MIPS16" | |
bb621ad7 JW |
8868 | [(set (match_dup 0) |
8869 | (ltu:DI (match_dup 2) | |
8870 | (match_dup 1))) | |
8871 | (set (match_dup 0) | |
8872 | (xor:DI (match_dup 0) | |
8873 | (const_int 1)))] | |
8874 | "") | |
8875 | ||
34b650b3 MM |
8876 | \f |
8877 | ;; | |
8878 | ;; .................... | |
8879 | ;; | |
8880 | ;; FLOATING POINT COMPARISONS | |
8881 | ;; | |
8882 | ;; .................... | |
8883 | ||
8884 | (define_insn "seq_df" | |
b8eb88d0 ILT |
8885 | [(set (match_operand:CC 0 "register_operand" "=z") |
8886 | (eq:CC (match_operand:DF 1 "register_operand" "f") | |
8887 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 8888 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
34b650b3 MM |
8889 | "* |
8890 | { | |
b8eb88d0 | 8891 | return mips_fill_delay_slot (\"c.eq.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8892 | }" |
8893 | [(set_attr "type" "fcmp") | |
0ff83799 | 8894 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8895 | |
8896 | (define_insn "slt_df" | |
b8eb88d0 ILT |
8897 | [(set (match_operand:CC 0 "register_operand" "=z") |
8898 | (lt:CC (match_operand:DF 1 "register_operand" "f") | |
8899 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 8900 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
34b650b3 MM |
8901 | "* |
8902 | { | |
b8eb88d0 | 8903 | return mips_fill_delay_slot (\"c.lt.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8904 | }" |
8905 | [(set_attr "type" "fcmp") | |
0ff83799 | 8906 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8907 | |
8908 | (define_insn "sle_df" | |
b8eb88d0 ILT |
8909 | [(set (match_operand:CC 0 "register_operand" "=z") |
8910 | (le:CC (match_operand:DF 1 "register_operand" "f") | |
8911 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 8912 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
34b650b3 MM |
8913 | "* |
8914 | { | |
b8eb88d0 | 8915 | return mips_fill_delay_slot (\"c.le.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8916 | }" |
8917 | [(set_attr "type" "fcmp") | |
0ff83799 | 8918 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8919 | |
8920 | (define_insn "sgt_df" | |
b8eb88d0 ILT |
8921 | [(set (match_operand:CC 0 "register_operand" "=z") |
8922 | (gt:CC (match_operand:DF 1 "register_operand" "f") | |
8923 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 8924 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
34b650b3 MM |
8925 | "* |
8926 | { | |
b8eb88d0 | 8927 | return mips_fill_delay_slot (\"c.lt.d\\t%Z0%2,%1\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8928 | }" |
8929 | [(set_attr "type" "fcmp") | |
0ff83799 | 8930 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8931 | |
8932 | (define_insn "sge_df" | |
b8eb88d0 ILT |
8933 | [(set (match_operand:CC 0 "register_operand" "=z") |
8934 | (ge:CC (match_operand:DF 1 "register_operand" "f") | |
8935 | (match_operand:DF 2 "register_operand" "f")))] | |
46299de9 | 8936 | "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
34b650b3 MM |
8937 | "* |
8938 | { | |
b8eb88d0 | 8939 | return mips_fill_delay_slot (\"c.le.d\\t%Z0%2,%1\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8940 | }" |
8941 | [(set_attr "type" "fcmp") | |
0ff83799 | 8942 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8943 | |
8944 | (define_insn "seq_sf" | |
b8eb88d0 ILT |
8945 | [(set (match_operand:CC 0 "register_operand" "=z") |
8946 | (eq:CC (match_operand:SF 1 "register_operand" "f") | |
8947 | (match_operand:SF 2 "register_operand" "f")))] | |
bb621ad7 | 8948 | "TARGET_HARD_FLOAT" |
34b650b3 MM |
8949 | "* |
8950 | { | |
b8eb88d0 | 8951 | return mips_fill_delay_slot (\"c.eq.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8952 | }" |
8953 | [(set_attr "type" "fcmp") | |
0ff83799 | 8954 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8955 | |
8956 | (define_insn "slt_sf" | |
b8eb88d0 ILT |
8957 | [(set (match_operand:CC 0 "register_operand" "=z") |
8958 | (lt:CC (match_operand:SF 1 "register_operand" "f") | |
8959 | (match_operand:SF 2 "register_operand" "f")))] | |
bb621ad7 | 8960 | "TARGET_HARD_FLOAT" |
34b650b3 MM |
8961 | "* |
8962 | { | |
b8eb88d0 | 8963 | return mips_fill_delay_slot (\"c.lt.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8964 | }" |
8965 | [(set_attr "type" "fcmp") | |
0ff83799 | 8966 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8967 | |
8968 | (define_insn "sle_sf" | |
b8eb88d0 ILT |
8969 | [(set (match_operand:CC 0 "register_operand" "=z") |
8970 | (le:CC (match_operand:SF 1 "register_operand" "f") | |
8971 | (match_operand:SF 2 "register_operand" "f")))] | |
bb621ad7 | 8972 | "TARGET_HARD_FLOAT" |
34b650b3 MM |
8973 | "* |
8974 | { | |
b8eb88d0 | 8975 | return mips_fill_delay_slot (\"c.le.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8976 | }" |
8977 | [(set_attr "type" "fcmp") | |
0ff83799 | 8978 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8979 | |
8980 | (define_insn "sgt_sf" | |
b8eb88d0 ILT |
8981 | [(set (match_operand:CC 0 "register_operand" "=z") |
8982 | (gt:CC (match_operand:SF 1 "register_operand" "f") | |
8983 | (match_operand:SF 2 "register_operand" "f")))] | |
bb621ad7 | 8984 | "TARGET_HARD_FLOAT" |
34b650b3 MM |
8985 | "* |
8986 | { | |
b8eb88d0 | 8987 | return mips_fill_delay_slot (\"c.lt.s\\t%Z0%2,%1\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
8988 | }" |
8989 | [(set_attr "type" "fcmp") | |
0ff83799 | 8990 | (set_attr "mode" "FPSW")]) |
34b650b3 MM |
8991 | |
8992 | (define_insn "sge_sf" | |
b8eb88d0 ILT |
8993 | [(set (match_operand:CC 0 "register_operand" "=z") |
8994 | (ge:CC (match_operand:SF 1 "register_operand" "f") | |
8995 | (match_operand:SF 2 "register_operand" "f")))] | |
bb621ad7 | 8996 | "TARGET_HARD_FLOAT" |
34b650b3 MM |
8997 | "* |
8998 | { | |
b8eb88d0 | 8999 | return mips_fill_delay_slot (\"c.le.s\\t%Z0%2,%1\", DELAY_FCMP, operands, insn); |
34b650b3 MM |
9000 | }" |
9001 | [(set_attr "type" "fcmp") | |
0ff83799 | 9002 | (set_attr "mode" "FPSW")]) |
34b650b3 | 9003 | |
8ef30996 MM |
9004 | \f |
9005 | ;; | |
9006 | ;; .................... | |
9007 | ;; | |
9008 | ;; UNCONDITIONAL BRANCHES | |
9009 | ;; | |
9010 | ;; .................... | |
9011 | ||
9012 | ;; Unconditional branches. | |
9013 | ||
9014 | (define_insn "jump" | |
9015 | [(set (pc) | |
9016 | (label_ref (match_operand 0 "" "")))] | |
2bcb2ab3 | 9017 | "!TARGET_MIPS16" |
8ef30996 MM |
9018 | "* |
9019 | { | |
9020 | if (GET_CODE (operands[0]) == REG) | |
9021 | return \"%*j\\t%0\"; | |
e19ff60f JW |
9022 | /* ??? I don't know why this is necessary. This works around an |
9023 | assembler problem that appears when a label is defined, then referenced | |
9024 | in a switch table, then used in a `j' instruction. */ | |
a53f72db | 9025 | else if (mips_abi != ABI_32 && mips_abi != ABI_O64) |
e19ff60f JW |
9026 | return \"%*b\\t%l0\"; |
9027 | else | |
8ef30996 MM |
9028 | return \"%*j\\t%l0\"; |
9029 | }" | |
9030 | [(set_attr "type" "jump") | |
0ff83799 | 9031 | (set_attr "mode" "none")]) |
8ef30996 | 9032 | |
2bcb2ab3 GK |
9033 | ;; We need a different insn for the mips16, because a mips16 branch |
9034 | ;; does not have a delay slot. | |
9035 | ||
9036 | (define_insn "" | |
9037 | [(set (pc) | |
9038 | (label_ref (match_operand 0 "" "")))] | |
9039 | "TARGET_MIPS16 && GET_CODE (operands[0]) != REG" | |
9040 | "b\\t%l0" | |
9041 | [(set_attr "type" "branch") | |
9042 | (set_attr "mode" "none") | |
0ff83799 | 9043 | (set_attr "length" "8")]) |
2bcb2ab3 | 9044 | |
bb621ad7 JW |
9045 | (define_expand "indirect_jump" |
9046 | [(set (pc) (match_operand 0 "register_operand" "d"))] | |
8ef30996 | 9047 | "" |
bb621ad7 JW |
9048 | " |
9049 | { | |
9050 | rtx dest; | |
9051 | ||
9052 | if (operands[0]) /* eliminate unused code warnings */ | |
9053 | { | |
9054 | dest = operands[0]; | |
9055 | if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) | |
9056 | operands[0] = copy_to_mode_reg (Pmode, dest); | |
9057 | ||
1eeed24e | 9058 | if (!(Pmode == DImode)) |
bb621ad7 JW |
9059 | emit_jump_insn (gen_indirect_jump_internal1 (operands[0])); |
9060 | else | |
9061 | emit_jump_insn (gen_indirect_jump_internal2 (operands[0])); | |
9062 | ||
9063 | DONE; | |
9064 | } | |
9065 | }") | |
9066 | ||
9067 | (define_insn "indirect_jump_internal1" | |
9068 | [(set (pc) (match_operand:SI 0 "register_operand" "d"))] | |
1eeed24e | 9069 | "!(Pmode == DImode)" |
bb621ad7 JW |
9070 | "%*j\\t%0" |
9071 | [(set_attr "type" "jump") | |
0ff83799 | 9072 | (set_attr "mode" "none")]) |
bb621ad7 JW |
9073 | |
9074 | (define_insn "indirect_jump_internal2" | |
1908a152 | 9075 | [(set (pc) (match_operand:DI 0 "se_register_operand" "d"))] |
1eeed24e | 9076 | "Pmode == DImode" |
8ef30996 MM |
9077 | "%*j\\t%0" |
9078 | [(set_attr "type" "jump") | |
0ff83799 | 9079 | (set_attr "mode" "none")]) |
8ef30996 | 9080 | |
bb621ad7 | 9081 | (define_expand "tablejump" |
8ef30996 | 9082 | [(set (pc) |
bb621ad7 | 9083 | (match_operand 0 "register_operand" "d")) |
8ef30996 MM |
9084 | (use (label_ref (match_operand 1 "" "")))] |
9085 | "" | |
bb621ad7 JW |
9086 | " |
9087 | { | |
bb621ad7 JW |
9088 | if (operands[0]) /* eliminate unused code warnings */ |
9089 | { | |
2bcb2ab3 GK |
9090 | if (TARGET_MIPS16) |
9091 | { | |
9092 | if (GET_MODE (operands[0]) != HImode) | |
9093 | abort (); | |
1eeed24e | 9094 | if (!(Pmode == DImode)) |
bf4f78ee | 9095 | emit_insn (gen_tablejump_mips161 (operands[0], operands[1])); |
2bcb2ab3 | 9096 | else |
bf4f78ee | 9097 | emit_insn (gen_tablejump_mips162 (operands[0], operands[1])); |
2bcb2ab3 GK |
9098 | DONE; |
9099 | } | |
9100 | ||
bb621ad7 JW |
9101 | if (GET_MODE (operands[0]) != Pmode) |
9102 | abort (); | |
9103 | ||
9fa0af71 JW |
9104 | if (! flag_pic) |
9105 | { | |
1eeed24e | 9106 | if (!(Pmode == DImode)) |
9fa0af71 JW |
9107 | emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1])); |
9108 | else | |
9109 | emit_jump_insn (gen_tablejump_internal2 (operands[0], operands[1])); | |
9110 | } | |
bb621ad7 | 9111 | else |
9fa0af71 | 9112 | { |
1eeed24e | 9113 | if (!(Pmode == DImode)) |
9fa0af71 JW |
9114 | emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1])); |
9115 | else | |
9116 | emit_jump_insn (gen_tablejump_internal4 (operands[0], operands[1])); | |
9117 | } | |
bb621ad7 JW |
9118 | |
9119 | DONE; | |
9120 | } | |
9121 | }") | |
9122 | ||
9123 | (define_insn "tablejump_internal1" | |
9124 | [(set (pc) | |
9125 | (match_operand:SI 0 "register_operand" "d")) | |
9126 | (use (label_ref (match_operand 1 "" "")))] | |
1eeed24e | 9127 | "!(Pmode == DImode)" |
9fa0af71 | 9128 | "%*j\\t%0" |
bb621ad7 | 9129 | [(set_attr "type" "jump") |
0ff83799 | 9130 | (set_attr "mode" "none")]) |
bb621ad7 JW |
9131 | |
9132 | (define_insn "tablejump_internal2" | |
9133 | [(set (pc) | |
1908a152 | 9134 | (match_operand:DI 0 "se_register_operand" "d")) |
bb621ad7 | 9135 | (use (label_ref (match_operand 1 "" "")))] |
1eeed24e | 9136 | "Pmode == DImode" |
9fa0af71 JW |
9137 | "%*j\\t%0" |
9138 | [(set_attr "type" "jump") | |
0ff83799 | 9139 | (set_attr "mode" "none")]) |
9fa0af71 JW |
9140 | |
9141 | (define_expand "tablejump_internal3" | |
5924eecf KR |
9142 | [(parallel [(set (pc) |
9143 | (plus:SI (match_operand:SI 0 "register_operand" "d") | |
cf45bb06 | 9144 | (label_ref:SI (match_operand 1 "" "")))) |
5924eecf | 9145 | (use (label_ref:SI (match_dup 1)))])] |
9fa0af71 JW |
9146 | "" |
9147 | "") | |
9148 | ||
2bcb2ab3 GK |
9149 | (define_expand "tablejump_mips161" |
9150 | [(set (pc) (plus:SI (sign_extend:SI | |
9151 | (match_operand:HI 0 "register_operand" "d")) | |
cf45bb06 | 9152 | (label_ref:SI (match_operand 1 "" ""))))] |
1eeed24e | 9153 | "TARGET_MIPS16 && !(Pmode == DImode)" |
2bcb2ab3 GK |
9154 | " |
9155 | { | |
9156 | if (operands[0]) /* eliminate unused code warnings. */ | |
9157 | { | |
9158 | rtx t1, t2, t3; | |
9159 | ||
9160 | t1 = gen_reg_rtx (SImode); | |
9161 | t2 = gen_reg_rtx (SImode); | |
9162 | t3 = gen_reg_rtx (SImode); | |
9163 | emit_insn (gen_extendhisi2 (t1, operands[0])); | |
9164 | emit_move_insn (t2, gen_rtx (LABEL_REF, SImode, operands[1])); | |
9165 | emit_insn (gen_addsi3 (t3, t1, t2)); | |
bf4f78ee | 9166 | emit_jump_insn (gen_tablejump_internal1 (t3, operands[1])); |
2bcb2ab3 GK |
9167 | DONE; |
9168 | } | |
9169 | }") | |
9170 | ||
9171 | (define_expand "tablejump_mips162" | |
9172 | [(set (pc) (plus:DI (sign_extend:DI | |
9173 | (match_operand:HI 0 "register_operand" "d")) | |
cf45bb06 | 9174 | (label_ref:DI (match_operand 1 "" ""))))] |
1eeed24e | 9175 | "TARGET_MIPS16 && Pmode == DImode" |
2bcb2ab3 GK |
9176 | " |
9177 | { | |
9178 | if (operands[0]) /* eliminate unused code warnings. */ | |
9179 | { | |
9180 | rtx t1, t2, t3; | |
9181 | ||
9182 | t1 = gen_reg_rtx (DImode); | |
9183 | t2 = gen_reg_rtx (DImode); | |
9184 | t3 = gen_reg_rtx (DImode); | |
9185 | emit_insn (gen_extendhidi2 (t1, operands[0])); | |
9186 | emit_move_insn (t2, gen_rtx (LABEL_REF, DImode, operands[1])); | |
9187 | emit_insn (gen_adddi3 (t3, t1, t2)); | |
bf4f78ee | 9188 | emit_jump_insn (gen_tablejump_internal2 (t3, operands[1])); |
2bcb2ab3 GK |
9189 | DONE; |
9190 | } | |
9191 | }") | |
9192 | ||
9fa0af71 | 9193 | ;;; Make sure that this only matches the insn before ADDR_DIFF_VEC. Otherwise |
05714a4f KR |
9194 | ;;; it is not valid. ??? With the USE, the condition tests may not be required |
9195 | ;;; any longer. | |
9fa0af71 JW |
9196 | |
9197 | ;;; ??? The length depends on the ABI. It is two for o32, and one for n32. | |
9198 | ;;; We just use the conservative number here. | |
9199 | ||
9200 | (define_insn "" | |
9201 | [(set (pc) | |
9202 | (plus:SI (match_operand:SI 0 "register_operand" "d") | |
cf45bb06 | 9203 | (label_ref:SI (match_operand 1 "" "")))) |
5924eecf | 9204 | (use (label_ref:SI (match_dup 1)))] |
1eeed24e | 9205 | "!(Pmode == DImode) && next_active_insn (insn) != 0 |
9fa0af71 JW |
9206 | && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC |
9207 | && PREV_INSN (next_active_insn (insn)) == operands[1]" | |
5a5b76a2 JW |
9208 | "* |
9209 | { | |
9fa0af71 | 9210 | /* .cpadd expands to add REG,REG,$gp when pic, and nothing when not pic. */ |
a53f72db | 9211 | if (mips_abi == ABI_32 || mips_abi == ABI_O64) |
e19ff60f | 9212 | output_asm_insn (\".cpadd\\t%0\", operands); |
5a5b76a2 JW |
9213 | return \"%*j\\t%0\"; |
9214 | }" | |
8ef30996 MM |
9215 | [(set_attr "type" "jump") |
9216 | (set_attr "mode" "none") | |
0ff83799 | 9217 | (set_attr "length" "8")]) |
9fa0af71 JW |
9218 | |
9219 | (define_expand "tablejump_internal4" | |
5924eecf KR |
9220 | [(parallel [(set (pc) |
9221 | (plus:DI (match_operand:DI 0 "se_register_operand" "d") | |
cf45bb06 | 9222 | (label_ref:DI (match_operand 1 "" "")))) |
5924eecf | 9223 | (use (label_ref:DI (match_dup 1)))])] |
9fa0af71 JW |
9224 | "" |
9225 | "") | |
9226 | ||
9227 | ;;; Make sure that this only matches the insn before ADDR_DIFF_VEC. Otherwise | |
05714a4f KR |
9228 | ;;; it is not valid. ??? With the USE, the condition tests may not be required |
9229 | ;;; any longer. | |
9fa0af71 JW |
9230 | |
9231 | (define_insn "" | |
9232 | [(set (pc) | |
1908a152 | 9233 | (plus:DI (match_operand:DI 0 "se_register_operand" "d") |
cf45bb06 | 9234 | (label_ref:DI (match_operand 1 "" "")))) |
5924eecf | 9235 | (use (label_ref:DI (match_dup 1)))] |
1eeed24e | 9236 | "Pmode == DImode && next_active_insn (insn) != 0 |
9fa0af71 JW |
9237 | && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC |
9238 | && PREV_INSN (next_active_insn (insn)) == operands[1]" | |
9239 | "%*j\\t%0" | |
9240 | [(set_attr "type" "jump") | |
0ff83799 | 9241 | (set_attr "mode" "none")]) |
8ef30996 | 9242 | |
e0bfcea5 ILT |
9243 | ;; Implement a switch statement when generating embedded PIC code. |
9244 | ;; Switches are implemented by `tablejump' when not using -membedded-pic. | |
9245 | ||
9246 | (define_expand "casesi" | |
9247 | [(set (match_dup 5) | |
9248 | (minus:SI (match_operand:SI 0 "register_operand" "d") | |
9249 | (match_operand:SI 1 "arith_operand" "dI"))) | |
9250 | (set (cc0) | |
9251 | (compare:CC (match_dup 5) | |
9252 | (match_operand:SI 2 "arith_operand" ""))) | |
9253 | (set (pc) | |
9254 | (if_then_else (gtu (cc0) | |
9255 | (const_int 0)) | |
9256 | (label_ref (match_operand 4 "" "")) | |
9257 | (pc))) | |
9258 | (parallel | |
9259 | [(set (pc) | |
9260 | (mem:SI (plus:SI (mult:SI (match_dup 5) | |
9261 | (const_int 4)) | |
9262 | (label_ref (match_operand 3 "" ""))))) | |
9263 | (clobber (match_scratch:SI 6 "")) | |
9264 | (clobber (reg:SI 31))])] | |
9265 | "TARGET_EMBEDDED_PIC" | |
9266 | " | |
9267 | { | |
e0bfcea5 ILT |
9268 | if (operands[0]) |
9269 | { | |
9270 | rtx reg = gen_reg_rtx (SImode); | |
9271 | ||
e0bfcea5 ILT |
9272 | /* If the index is too large, go to the default label. */ |
9273 | emit_insn (gen_subsi3 (reg, operands[0], operands[1])); | |
9274 | emit_insn (gen_cmpsi (reg, operands[2])); | |
9275 | emit_insn (gen_bgtu (operands[4])); | |
9276 | ||
9277 | /* Do the PIC jump. */ | |
9c9e7632 GK |
9278 | if (Pmode != DImode) |
9279 | emit_jump_insn (gen_casesi_internal (reg, operands[3], | |
9280 | gen_reg_rtx (SImode))); | |
9281 | else | |
9282 | emit_jump_insn (gen_casesi_internal_di (reg, operands[3], | |
9283 | gen_reg_rtx (DImode))); | |
e0bfcea5 ILT |
9284 | |
9285 | DONE; | |
9286 | } | |
9287 | }") | |
9288 | ||
9289 | ;; An embedded PIC switch statement looks like this: | |
9290 | ;; bal $LS1 | |
810c1b83 | 9291 | ;; sll $reg,$index,2 |
e0bfcea5 ILT |
9292 | ;; $LS1: |
9293 | ;; addu $reg,$reg,$31 | |
9294 | ;; lw $reg,$L1-$LS1($reg) | |
9295 | ;; addu $reg,$reg,$31 | |
9296 | ;; j $reg | |
9297 | ;; $L1: | |
9298 | ;; .word case1-$LS1 | |
9299 | ;; .word case2-$LS1 | |
9300 | ;; ... | |
9301 | ||
9302 | (define_insn "casesi_internal" | |
9303 | [(set (pc) | |
9304 | (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "d") | |
9305 | (const_int 4)) | |
9306 | (label_ref (match_operand 1 "" ""))))) | |
0e7e9155 | 9307 | (clobber (match_operand:SI 2 "register_operand" "=d")) |
e0bfcea5 ILT |
9308 | (clobber (reg:SI 31))] |
9309 | "TARGET_EMBEDDED_PIC" | |
810c1b83 RH |
9310 | "%(bal\\t%S1\;sll\\t%2,%0,2\\n%~%S1:\;addu\\t%2,%2,$31%)\;\\ |
9311 | lw\\t%2,%1-%S1(%2)\;addu\\t%2,%2,$31\;j\\t%2" | |
e0bfcea5 ILT |
9312 | [(set_attr "type" "jump") |
9313 | (set_attr "mode" "none") | |
0ff83799 | 9314 | (set_attr "length" "24")]) |
e0bfcea5 | 9315 | |
9c9e7632 GK |
9316 | (define_insn "casesi_internal_di" |
9317 | [(set (pc) | |
9318 | (mem:DI (plus:DI (sign_extend:DI | |
9319 | (mult:SI (match_operand:SI 0 "register_operand" "d") | |
58dbe05f | 9320 | (const_int 4))) |
9c9e7632 GK |
9321 | (label_ref (match_operand 1 "" ""))))) |
9322 | (clobber (match_operand:DI 2 "register_operand" "=d")) | |
9323 | (clobber (reg:DI 31))] | |
9324 | "TARGET_EMBEDDED_PIC" | |
9325 | "%(bal\\t%S1\;sll\\t%2,%0,2\\n%~%S1:\;addu\\t%2,%2,$31%)\;\\ | |
9326 | ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\;j\\t%2" | |
9327 | [(set_attr "type" "jump") | |
9328 | (set_attr "mode" "none") | |
9329 | (set_attr "length" "24")]) | |
9330 | ||
6fd1c67b RH |
9331 | ;; For o32/n32/n64, we save the gp in the jmp_buf as well. While it is |
9332 | ;; possible to either pull it off the stack (in the o32 case) or recalculate | |
9333 | ;; it given t9 and our target label, it takes 3 or 4 insns to do so, and | |
9334 | ;; this is easy. | |
9335 | ||
9336 | (define_expand "builtin_setjmp_setup" | |
9337 | [(unspec [(match_operand 0 "register_operand" "r")] 20)] | |
9338 | "TARGET_ABICALLS" | |
d5d1738a JW |
9339 | " |
9340 | { | |
1eeed24e | 9341 | if (Pmode == DImode) |
6fd1c67b RH |
9342 | emit_insn (gen_builtin_setjmp_setup_64 (operands[0])); |
9343 | else | |
9344 | emit_insn (gen_builtin_setjmp_setup_32 (operands[0])); | |
9345 | DONE; | |
d5d1738a | 9346 | }") |
c85f7c16 | 9347 | |
6fd1c67b RH |
9348 | (define_expand "builtin_setjmp_setup_32" |
9349 | [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r") | |
9350 | (const_int 12))) | |
9351 | (reg:SI 28))] | |
1eeed24e | 9352 | "TARGET_ABICALLS && ! (Pmode == DImode)" |
6fd1c67b | 9353 | "") |
c85f7c16 | 9354 | |
6fd1c67b RH |
9355 | (define_expand "builtin_setjmp_setup_64" |
9356 | [(set (mem:DI (plus:DI (match_operand:DI 0 "register_operand" "r") | |
9357 | (const_int 24))) | |
9358 | (reg:DI 28))] | |
1eeed24e | 9359 | "TARGET_ABICALLS && Pmode == DImode" |
6fd1c67b RH |
9360 | "") |
9361 | ||
9362 | ;; For o32/n32/n64, we need to arrange for longjmp to put the | |
9363 | ;; target address in t9 so that we can use it for loading $gp. | |
9364 | ||
9365 | (define_expand "builtin_longjmp" | |
9366 | [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] | |
9367 | "TARGET_ABICALLS" | |
c85f7c16 JL |
9368 | " |
9369 | { | |
6fd1c67b | 9370 | /* The elements of the buffer are, in order: */ |
1eeed24e | 9371 | int W = (Pmode == DImode ? 8 : 4); |
6fd1c67b RH |
9372 | rtx fp = gen_rtx_MEM (Pmode, operands[0]); |
9373 | rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W)); | |
9374 | rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W)); | |
9375 | rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W)); | |
9376 | rtx pv = gen_rtx_REG (Pmode, 25); | |
9377 | rtx gp = gen_rtx_REG (Pmode, 28); | |
9378 | ||
9379 | /* This bit is the same as expand_builtin_longjmp. */ | |
9380 | emit_move_insn (hard_frame_pointer_rtx, fp); | |
9381 | emit_move_insn (pv, lab); | |
9382 | emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); | |
9383 | emit_move_insn (gp, gpv); | |
9384 | emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); | |
9385 | emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); | |
9386 | emit_insn (gen_rtx_USE (VOIDmode, gp)); | |
9387 | emit_indirect_jump (pv); | |
9388 | DONE; | |
c85f7c16 | 9389 | }") |
0fb5ac6f MM |
9390 | \f |
9391 | ;; | |
9392 | ;; .................... | |
9393 | ;; | |
9394 | ;; Function prologue/epilogue | |
9395 | ;; | |
9396 | ;; .................... | |
9397 | ;; | |
9398 | ||
9399 | (define_expand "prologue" | |
9400 | [(const_int 1)] | |
9401 | "" | |
9402 | " | |
9403 | { | |
9404 | if (mips_isa >= 0) /* avoid unused code warnings */ | |
9405 | { | |
9406 | mips_expand_prologue (); | |
9407 | DONE; | |
9408 | } | |
9409 | }") | |
9410 | ||
d8d5b1e1 MM |
9411 | ;; Block any insns from being moved before this point, since the |
9412 | ;; profiling call to mcount can use various registers that aren't | |
9413 | ;; saved or used to pass arguments. | |
9414 | ||
9415 | (define_insn "blockage" | |
9416 | [(unspec_volatile [(const_int 0)] 0)] | |
9417 | "" | |
9418 | "" | |
9419 | [(set_attr "type" "unknown") | |
9420 | (set_attr "mode" "none") | |
9421 | (set_attr "length" "0")]) | |
9422 | ||
1f2d8f51 JL |
9423 | (define_expand "epilogue" |
9424 | [(const_int 2)] | |
9425 | "" | |
9426 | " | |
9427 | { | |
9428 | if (mips_isa >= 0) /* avoid unused code warnings */ | |
9429 | { | |
9430 | mips_expand_epilogue (); | |
9431 | DONE; | |
9432 | } | |
9433 | }") | |
0fb5ac6f | 9434 | |
1f2d8f51 JL |
9435 | ;; Trivial return. Make it look like a normal return insn as that |
9436 | ;; allows jump optimizations to work better . | |
9437 | (define_insn "return" | |
9438 | [(return)] | |
9439 | "mips_can_use_return_insn ()" | |
8fa4e1b4 | 9440 | "%*j\\t$31" |
1f2d8f51 | 9441 | [(set_attr "type" "jump") |
0ff83799 | 9442 | (set_attr "mode" "none")]) |
1f2d8f51 JL |
9443 | |
9444 | ;; Normal return. | |
0e7e9155 | 9445 | |
1f2d8f51 | 9446 | (define_insn "return_internal" |
0e7e9155 | 9447 | [(use (match_operand 0 "pmode_register_operand" "")) |
1f2d8f51 JL |
9448 | (return)] |
9449 | "" | |
2bcb2ab3 GK |
9450 | "* |
9451 | { | |
9452 | return \"%*j\\t%0\"; | |
9453 | }" | |
1f2d8f51 | 9454 | [(set_attr "type" "jump") |
0ff83799 | 9455 | (set_attr "mode" "none")]) |
1f2d8f51 | 9456 | |
92544bdf ILT |
9457 | ;; When generating embedded PIC code we need to get the address of the |
9458 | ;; current function. This specialized instruction does just that. | |
9459 | ||
9460 | (define_insn "get_fnaddr" | |
0d3b5987 | 9461 | [(set (match_operand 0 "register_operand" "=d") |
92544bdf ILT |
9462 | (unspec [(match_operand 1 "" "")] 1)) |
9463 | (clobber (reg:SI 31))] | |
9464 | "TARGET_EMBEDDED_PIC | |
9465 | && GET_CODE (operands[1]) == SYMBOL_REF" | |
9466 | "%($LF%= = . + 8\;bal\\t$LF%=\;la\\t%0,%1-$LF%=%)\;addu\\t%0,%0,$31" | |
9467 | [(set_attr "type" "call") | |
9468 | (set_attr "mode" "none") | |
0ff83799 | 9469 | (set_attr "length" "16")]) |
92544bdf | 9470 | |
8ef30996 MM |
9471 | \f |
9472 | ;; | |
9473 | ;; .................... | |
9474 | ;; | |
9475 | ;; FUNCTION CALLS | |
9476 | ;; | |
9477 | ;; .................... | |
9478 | ||
9479 | ;; calls.c now passes a third argument, make saber happy | |
9480 | ||
9481 | (define_expand "call" | |
af4a697f | 9482 | [(parallel [(call (match_operand 0 "memory_operand" "m") |
8ef30996 | 9483 | (match_operand 1 "" "i")) |
3f1f8d8c MM |
9484 | (clobber (reg:SI 31)) |
9485 | (use (match_operand 2 "" "")) ;; next_arg_reg | |
9486 | (use (match_operand 3 "" ""))])] ;; struct_value_size_rtx | |
8ef30996 MM |
9487 | "" |
9488 | " | |
9489 | { | |
9490 | rtx addr; | |
9491 | ||
3f1f8d8c MM |
9492 | if (operands[0]) /* eliminate unused code warnings */ |
9493 | { | |
9494 | addr = XEXP (operands[0], 0); | |
322dce45 | 9495 | if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS)) |
aa4e54c4 | 9496 | || ! call_insn_operand (addr, VOIDmode)) |
322dce45 | 9497 | XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr); |
3f1f8d8c MM |
9498 | |
9499 | /* In order to pass small structures by value in registers | |
9500 | compatibly with the MIPS compiler, we need to shift the value | |
9501 | into the high part of the register. Function_arg has encoded | |
9502 | a PARALLEL rtx, holding a vector of adjustments to be made | |
9503 | as the next_arg_reg variable, so we split up the insns, | |
9504 | and emit them separately. */ | |
9505 | ||
9506 | if (operands[2] != (rtx)0 && GET_CODE (operands[2]) == PARALLEL) | |
9507 | { | |
9508 | rtvec adjust = XVEC (operands[2], 0); | |
9509 | int num = GET_NUM_ELEM (adjust); | |
9510 | int i; | |
9511 | ||
9512 | for (i = 0; i < num; i++) | |
9513 | emit_insn (RTVEC_ELT (adjust, i)); | |
9514 | } | |
8ef30996 | 9515 | |
2bcb2ab3 GK |
9516 | if (TARGET_MIPS16 |
9517 | && mips16_hard_float | |
9518 | && operands[2] != 0 | |
9519 | && (int) GET_MODE (operands[2]) != 0) | |
9520 | { | |
9521 | if (build_mips16_call_stub (NULL_RTX, operands[0], operands[1], | |
9522 | (int) GET_MODE (operands[2]))) | |
9523 | DONE; | |
9524 | } | |
9525 | ||
aa4e54c4 | 9526 | emit_call_insn (gen_call_internal0 (operands[0], operands[1], |
c5c76735 JL |
9527 | gen_rtx_REG (SImode, |
9528 | GP_REG_FIRST + 31))); | |
3f1f8d8c MM |
9529 | DONE; |
9530 | } | |
8ef30996 MM |
9531 | }") |
9532 | ||
aa4e54c4 JW |
9533 | (define_expand "call_internal0" |
9534 | [(parallel [(call (match_operand 0 "" "") | |
9535 | (match_operand 1 "" "")) | |
9536 | (clobber (match_operand:SI 2 "" ""))])] | |
9537 | "" | |
9538 | "") | |
9539 | ||
2bcb2ab3 GK |
9540 | ;; We need to recognize reg:SI 31 specially for the mips16, because we |
9541 | ;; don't have a constraint letter for it. | |
9542 | ||
9543 | (define_insn "" | |
9544 | [(call (mem (match_operand 0 "call_insn_operand" "ei")) | |
9545 | (match_operand 1 "" "i")) | |
9546 | (clobber (match_operand:SI 2 "register_operand" "=y"))] | |
9547 | "TARGET_MIPS16 && !TARGET_ABICALLS && !TARGET_LONG_CALLS | |
9548 | && GET_CODE (operands[2]) == REG && REGNO (operands[2]) == 31" | |
9549 | "%*jal\\t%0" | |
9550 | [(set_attr "type" "call") | |
9551 | (set_attr "mode" "none") | |
0ff83799 | 9552 | (set_attr "length" "8")]) |
2bcb2ab3 | 9553 | |
d1399bd0 | 9554 | (define_insn "call_internal1" |
aa4e54c4 | 9555 | [(call (mem (match_operand 0 "call_insn_operand" "ri")) |
8ef30996 MM |
9556 | (match_operand 1 "" "i")) |
9557 | (clobber (match_operand:SI 2 "register_operand" "=d"))] | |
84a92af4 | 9558 | "!TARGET_ABICALLS && !TARGET_LONG_CALLS" |
8ef30996 MM |
9559 | "* |
9560 | { | |
aa4e54c4 | 9561 | register rtx target = operands[0]; |
8ef30996 MM |
9562 | |
9563 | if (GET_CODE (target) == SYMBOL_REF) | |
9564 | return \"%*jal\\t%0\"; | |
2bba3a75 | 9565 | else if (GET_CODE (target) == CONST_INT) |
5aae9091 | 9566 | return \"%[li\\t%@,%0\\n\\t%*jal\\t%2,%@%]\"; |
8ef30996 | 9567 | else |
5aae9091 | 9568 | return \"%*jal\\t%2,%0\"; |
8ef30996 MM |
9569 | }" |
9570 | [(set_attr "type" "call") | |
0ff83799 | 9571 | (set_attr "mode" "none")]) |
8ef30996 | 9572 | |
d1399bd0 | 9573 | (define_insn "call_internal2" |
aa4e54c4 | 9574 | [(call (mem (match_operand 0 "call_insn_operand" "ri")) |
84a92af4 JW |
9575 | (match_operand 1 "" "i")) |
9576 | (clobber (match_operand:SI 2 "register_operand" "=d"))] | |
9577 | "TARGET_ABICALLS && !TARGET_LONG_CALLS" | |
9578 | "* | |
9579 | { | |
aa4e54c4 | 9580 | register rtx target = operands[0]; |
84a92af4 JW |
9581 | |
9582 | if (GET_CODE (target) == SYMBOL_REF) | |
84a92af4 | 9583 | { |
5aae9091 JW |
9584 | if (GET_MODE (target) == SImode) |
9585 | return \"la\\t%^,%0\\n\\tjal\\t%2,%^\"; | |
84a92af4 | 9586 | else |
5aae9091 | 9587 | return \"dla\\t%^,%0\\n\\tjal\\t%2,%^\"; |
84a92af4 | 9588 | } |
5aae9091 JW |
9589 | else if (GET_CODE (target) == CONST_INT) |
9590 | return \"li\\t%^,%0\\n\\tjal\\t%2,%^\"; | |
9591 | else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM) | |
9592 | return \"move\\t%^,%0\\n\\tjal\\t%2,%^\"; | |
9593 | else | |
9594 | return \"jal\\t%2,%0\"; | |
84a92af4 JW |
9595 | }" |
9596 | [(set_attr "type" "call") | |
9597 | (set_attr "mode" "none") | |
0ff83799 | 9598 | (set_attr "length" "8")]) |
84a92af4 | 9599 | |
bb621ad7 | 9600 | (define_insn "call_internal3a" |
d1399bd0 MM |
9601 | [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) |
9602 | (match_operand 1 "" "i")) | |
9603 | (clobber (match_operand:SI 2 "register_operand" "=d"))] | |
8da665d5 SC |
9604 | "!TARGET_MIPS16 |
9605 | && !(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS" | |
bb621ad7 JW |
9606 | "%*jal\\t%2,%0" |
9607 | [(set_attr "type" "call") | |
0ff83799 | 9608 | (set_attr "mode" "none")]) |
bb621ad7 JW |
9609 | |
9610 | (define_insn "call_internal3b" | |
1908a152 | 9611 | [(call (mem:DI (match_operand:DI 0 "se_register_operand" "r")) |
bb621ad7 JW |
9612 | (match_operand 1 "" "i")) |
9613 | (clobber (match_operand:SI 2 "register_operand" "=d"))] | |
8da665d5 SC |
9614 | "!TARGET_MIPS16 |
9615 | && Pmode == DImode && !TARGET_ABICALLS && TARGET_LONG_CALLS" | |
9616 | "%*jal\\t%2,%0" | |
9617 | [(set_attr "type" "call") | |
9618 | (set_attr "mode" "none") | |
9619 | (set_attr "length" "1")]) | |
9620 | ||
9621 | (define_insn "call_internal3c" | |
9622 | [(call (mem:SI (match_operand:SI 0 "register_operand" "e")) | |
9623 | (match_operand 1 "" "i")) | |
9624 | (clobber (match_operand:SI 2 "register_operand" "=y"))] | |
9625 | "TARGET_MIPS16 && !(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS | |
9626 | && GET_CODE (operands[2]) == REG && REGNO (operands[2]) == 31" | |
d1399bd0 MM |
9627 | "%*jal\\t%2,%0" |
9628 | [(set_attr "type" "call") | |
0ff83799 | 9629 | (set_attr "mode" "none")]) |
d1399bd0 | 9630 | |
bb621ad7 | 9631 | (define_insn "call_internal4a" |
84a92af4 JW |
9632 | [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) |
9633 | (match_operand 1 "" "i")) | |
9634 | (clobber (match_operand:SI 2 "register_operand" "=d"))] | |
1eeed24e | 9635 | "!(Pmode == DImode) && TARGET_ABICALLS && TARGET_LONG_CALLS" |
84a92af4 JW |
9636 | "* |
9637 | { | |
9638 | if (REGNO (operands[0]) != PIC_FUNCTION_ADDR_REGNUM) | |
9639 | return \"move\\t%^,%0\\n\\tjal\\t%2,%^\"; | |
9640 | else | |
9641 | return \"jal\\t%2,%0\"; | |
9642 | }" | |
9643 | [(set_attr "type" "call") | |
9644 | (set_attr "mode" "none") | |
0ff83799 | 9645 | (set_attr "length" "8")]) |
84a92af4 | 9646 | |
bb621ad7 | 9647 | (define_insn "call_internal4b" |
1908a152 | 9648 | [(call (mem:DI (match_operand:DI 0 "se_register_operand" "r")) |
bb621ad7 JW |
9649 | (match_operand 1 "" "i")) |
9650 | (clobber (match_operand:SI 2 "register_operand" "=d"))] | |
1eeed24e | 9651 | "Pmode == DImode && TARGET_ABICALLS && TARGET_LONG_CALLS" |
bb621ad7 JW |
9652 | "* |
9653 | { | |
9654 | if (REGNO (operands[0]) != PIC_FUNCTION_ADDR_REGNUM) | |
9655 | return \"move\\t%^,%0\\n\\tjal\\t%2,%^\"; | |
9656 | else | |
9657 | return \"jal\\t%2,%0\"; | |
9658 | }" | |
9659 | [(set_attr "type" "call") | |
9660 | (set_attr "mode" "none") | |
0ff83799 | 9661 | (set_attr "length" "8")]) |
d1399bd0 | 9662 | |
8ef30996 MM |
9663 | ;; calls.c now passes a fourth argument, make saber happy |
9664 | ||
9665 | (define_expand "call_value" | |
9666 | [(parallel [(set (match_operand 0 "register_operand" "=df") | |
af4a697f | 9667 | (call (match_operand 1 "memory_operand" "m") |
8ef30996 | 9668 | (match_operand 2 "" "i"))) |
3f1f8d8c MM |
9669 | (clobber (reg:SI 31)) |
9670 | (use (match_operand 3 "" ""))])] ;; next_arg_reg | |
8ef30996 MM |
9671 | "" |
9672 | " | |
9673 | { | |
9674 | rtx addr; | |
9675 | ||
3f1f8d8c MM |
9676 | if (operands[0]) /* eliminate unused code warning */ |
9677 | { | |
9678 | addr = XEXP (operands[1], 0); | |
322dce45 | 9679 | if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS)) |
aa4e54c4 | 9680 | || ! call_insn_operand (addr, VOIDmode)) |
322dce45 | 9681 | XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr); |
3f1f8d8c MM |
9682 | |
9683 | /* In order to pass small structures by value in registers | |
9684 | compatibly with the MIPS compiler, we need to shift the value | |
9685 | into the high part of the register. Function_arg has encoded | |
9686 | a PARALLEL rtx, holding a vector of adjustments to be made | |
9687 | as the next_arg_reg variable, so we split up the insns, | |
9688 | and emit them separately. */ | |
9689 | ||
9690 | if (operands[3] != (rtx)0 && GET_CODE (operands[3]) == PARALLEL) | |
9691 | { | |
9692 | rtvec adjust = XVEC (operands[3], 0); | |
9693 | int num = GET_NUM_ELEM (adjust); | |
9694 | int i; | |
9695 | ||
9696 | for (i = 0; i < num; i++) | |
9697 | emit_insn (RTVEC_ELT (adjust, i)); | |
9698 | } | |
9699 | ||
2bcb2ab3 GK |
9700 | if (TARGET_MIPS16 |
9701 | && mips16_hard_float | |
9702 | && ((operands[3] != 0 | |
9703 | && (int) GET_MODE (operands[3]) != 0) | |
9704 | || GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_FLOAT)) | |
9705 | { | |
9706 | if (build_mips16_call_stub (operands[0], operands[1], operands[2], | |
9707 | (operands[3] == 0 ? 0 | |
9708 | : (int) GET_MODE (operands[3])))) | |
9709 | DONE; | |
9710 | } | |
9711 | ||
bd16a708 JW |
9712 | /* Handle Irix6 function calls that have multiple non-contiguous |
9713 | results. */ | |
f7a61b83 | 9714 | if (GET_CODE (operands[0]) == PARALLEL && XVECLEN (operands[0], 0) > 1) |
bd16a708 | 9715 | { |
aa4e54c4 | 9716 | emit_call_insn (gen_call_value_multiple_internal0 |
bd16a708 JW |
9717 | (XEXP (XVECEXP (operands[0], 0, 0), 0), |
9718 | operands[1], operands[2], | |
9719 | XEXP (XVECEXP (operands[0], 0, 1), 0), | |
c5c76735 | 9720 | gen_rtx_REG (SImode, GP_REG_FIRST + 31))); |
bd16a708 JW |
9721 | DONE; |
9722 | } | |
9723 | ||
f7a61b83 JW |
9724 | /* We have a call returning a DImode structure in an FP reg. |
9725 | Strip off the now unnecessary PARALLEL. */ | |
9726 | if (GET_CODE (operands[0]) == PARALLEL) | |
9727 | operands[0] = XEXP (XVECEXP (operands[0], 0, 0), 0); | |
9728 | ||
aa4e54c4 | 9729 | emit_call_insn (gen_call_value_internal0 (operands[0], operands[1], operands[2], |
c5c76735 JL |
9730 | gen_rtx_REG (SImode, |
9731 | GP_REG_FIRST + 31))); | |
3f1f8d8c MM |
9732 | |
9733 | DONE; | |
9734 | } | |
8ef30996 MM |
9735 | }") |
9736 | ||
aa4e54c4 JW |
9737 | (define_expand "call_value_internal0" |
9738 | [(parallel [(set (match_operand 0 "" "") | |
9739 | (call (match_operand 1 "" "") | |
9740 | (match_operand 2 "" ""))) | |
9741 | (clobber (match_operand:SI 3 "" ""))])] | |
9742 | "" | |
9743 | "") | |
9744 | ||
2bcb2ab3 GK |
9745 | ;; Recognize $31 specially on the mips16, because we don't have a |
9746 | ;; constraint letter for it. | |
9747 | ||
9748 | (define_insn "" | |
9749 | [(set (match_operand 0 "register_operand" "=d") | |
9750 | (call (mem (match_operand 1 "call_insn_operand" "ei")) | |
9751 | (match_operand 2 "" "i"))) | |
9752 | (clobber (match_operand:SI 3 "register_operand" "=y"))] | |
9753 | "TARGET_MIPS16 && !TARGET_ABICALLS && !TARGET_LONG_CALLS | |
9754 | && GET_CODE (operands[3]) == REG && REGNO (operands[3]) == 31" | |
9755 | "%*jal\\t%1" | |
9756 | [(set_attr "type" "call") | |
9757 | (set_attr "mode" "none") | |
0ff83799 | 9758 | (set_attr "length" "8")]) |
2bcb2ab3 | 9759 | |
d1399bd0 | 9760 | (define_insn "call_value_internal1" |
8ef30996 | 9761 | [(set (match_operand 0 "register_operand" "=df") |
aa4e54c4 | 9762 | (call (mem (match_operand 1 "call_insn_operand" "ri")) |
8ef30996 MM |
9763 | (match_operand 2 "" "i"))) |
9764 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
84a92af4 | 9765 | "!TARGET_ABICALLS && !TARGET_LONG_CALLS" |
8ef30996 MM |
9766 | "* |
9767 | { | |
aa4e54c4 | 9768 | register rtx target = operands[1]; |
8ef30996 MM |
9769 | |
9770 | if (GET_CODE (target) == SYMBOL_REF) | |
9771 | return \"%*jal\\t%1\"; | |
2bba3a75 | 9772 | else if (GET_CODE (target) == CONST_INT) |
5aae9091 | 9773 | return \"%[li\\t%@,%1\\n\\t%*jal\\t%3,%@%]\"; |
8ef30996 | 9774 | else |
5aae9091 | 9775 | return \"%*jal\\t%3,%1\"; |
8ef30996 MM |
9776 | }" |
9777 | [(set_attr "type" "call") | |
0ff83799 | 9778 | (set_attr "mode" "none")]) |
8ef30996 | 9779 | |
d1399bd0 | 9780 | (define_insn "call_value_internal2" |
84a92af4 | 9781 | [(set (match_operand 0 "register_operand" "=df") |
aa4e54c4 | 9782 | (call (mem (match_operand 1 "call_insn_operand" "ri")) |
84a92af4 JW |
9783 | (match_operand 2 "" "i"))) |
9784 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
9785 | "TARGET_ABICALLS && !TARGET_LONG_CALLS" | |
9786 | "* | |
9787 | { | |
aa4e54c4 | 9788 | register rtx target = operands[1]; |
84a92af4 JW |
9789 | |
9790 | if (GET_CODE (target) == SYMBOL_REF) | |
84a92af4 | 9791 | { |
5aae9091 JW |
9792 | if (GET_MODE (target) == SImode) |
9793 | return \"la\\t%^,%1\\n\\tjal\\t%3,%^\"; | |
84a92af4 | 9794 | else |
5aae9091 | 9795 | return \"dla\\t%^,%1\\n\\tjal\\t%3,%^\"; |
84a92af4 | 9796 | } |
5aae9091 JW |
9797 | else if (GET_CODE (target) == CONST_INT) |
9798 | return \"li\\t%^,%1\\n\\tjal\\t%3,%^\"; | |
9799 | else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM) | |
9800 | return \"move\\t%^,%1\\n\\tjal\\t%3,%^\"; | |
9801 | else | |
9802 | return \"jal\\t%3,%1\"; | |
84a92af4 JW |
9803 | }" |
9804 | [(set_attr "type" "call") | |
9805 | (set_attr "mode" "none") | |
0ff83799 | 9806 | (set_attr "length" "8")]) |
84a92af4 | 9807 | |
bb621ad7 | 9808 | (define_insn "call_value_internal3a" |
d1399bd0 MM |
9809 | [(set (match_operand 0 "register_operand" "=df") |
9810 | (call (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
9811 | (match_operand 2 "" "i"))) | |
9812 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
6d4503c3 SC |
9813 | "!TARGET_MIPS16 |
9814 | && !(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS" | |
bb621ad7 JW |
9815 | "%*jal\\t%3,%1" |
9816 | [(set_attr "type" "call") | |
0ff83799 | 9817 | (set_attr "mode" "none")]) |
bb621ad7 JW |
9818 | |
9819 | (define_insn "call_value_internal3b" | |
9820 | [(set (match_operand 0 "register_operand" "=df") | |
1908a152 | 9821 | (call (mem:DI (match_operand:DI 1 "se_register_operand" "r")) |
bb621ad7 JW |
9822 | (match_operand 2 "" "i"))) |
9823 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
6d4503c3 SC |
9824 | "!TARGET_MIPS16 |
9825 | && Pmode == DImode && !TARGET_ABICALLS && TARGET_LONG_CALLS" | |
9826 | "%*jal\\t%3,%1" | |
9827 | [(set_attr "type" "call") | |
0ff83799 | 9828 | (set_attr "mode" "none")]) |
6d4503c3 SC |
9829 | |
9830 | (define_insn "call_value_internal3c" | |
9831 | [(set (match_operand 0 "register_operand" "=df") | |
9832 | (call (mem:SI (match_operand:SI 1 "register_operand" "e")) | |
9833 | (match_operand 2 "" "i"))) | |
9834 | (clobber (match_operand:SI 3 "register_operand" "=y"))] | |
9835 | "TARGET_MIPS16 && !(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS | |
9836 | && GET_CODE (operands[3]) == REG && REGNO (operands[3]) == 31" | |
d1399bd0 MM |
9837 | "%*jal\\t%3,%1" |
9838 | [(set_attr "type" "call") | |
0ff83799 | 9839 | (set_attr "mode" "none")]) |
d1399bd0 | 9840 | |
bb621ad7 | 9841 | (define_insn "call_value_internal4a" |
84a92af4 JW |
9842 | [(set (match_operand 0 "register_operand" "=df") |
9843 | (call (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
9844 | (match_operand 2 "" "i"))) | |
9845 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
1eeed24e | 9846 | "!(Pmode == DImode) && TARGET_ABICALLS && TARGET_LONG_CALLS" |
bb621ad7 JW |
9847 | "* |
9848 | { | |
9849 | if (REGNO (operands[1]) != PIC_FUNCTION_ADDR_REGNUM) | |
9850 | return \"move\\t%^,%1\\n\\tjal\\t%3,%^\"; | |
9851 | else | |
9852 | return \"jal\\t%3,%1\"; | |
9853 | }" | |
9854 | [(set_attr "type" "call") | |
9855 | (set_attr "mode" "none") | |
0ff83799 | 9856 | (set_attr "length" "8")]) |
bb621ad7 JW |
9857 | |
9858 | (define_insn "call_value_internal4b" | |
9859 | [(set (match_operand 0 "register_operand" "=df") | |
1908a152 | 9860 | (call (mem:DI (match_operand:DI 1 "se_register_operand" "r")) |
bb621ad7 JW |
9861 | (match_operand 2 "" "i"))) |
9862 | (clobber (match_operand:SI 3 "register_operand" "=d"))] | |
1eeed24e | 9863 | "Pmode == DImode && TARGET_ABICALLS && TARGET_LONG_CALLS" |
84a92af4 JW |
9864 | "* |
9865 | { | |
9866 | if (REGNO (operands[1]) != PIC_FUNCTION_ADDR_REGNUM) | |
9867 | return \"move\\t%^,%1\\n\\tjal\\t%3,%^\"; | |
9868 | else | |
9869 | return \"jal\\t%3,%1\"; | |
9870 | }" | |
9871 | [(set_attr "type" "call") | |
9872 | (set_attr "mode" "none") | |
0ff83799 | 9873 | (set_attr "length" "8")]) |
84a92af4 | 9874 | |
a5262009 | 9875 | (define_expand "call_value_multiple_internal0" |
aa4e54c4 JW |
9876 | [(parallel [(set (match_operand 0 "" "") |
9877 | (call (match_operand 1 "" "") | |
9878 | (match_operand 2 "" ""))) | |
9879 | (set (match_operand 3 "" "") | |
9880 | (call (match_dup 1) | |
9881 | (match_dup 2))) | |
9882 | (clobber (match_operand:SI 4 "" ""))])] | |
9883 | "" | |
9884 | "") | |
9885 | ||
bd16a708 JW |
9886 | ;; ??? May eventually need all 6 versions of the call patterns with multiple |
9887 | ;; return values. | |
9888 | ||
8f7f2b3d GRK |
9889 | (define_insn "call_value_multiple_internal1" |
9890 | [(set (match_operand 0 "register_operand" "=df") | |
9891 | (call (mem (match_operand 1 "call_insn_operand" "ri")) | |
9892 | (match_operand 2 "" "i"))) | |
9893 | (set (match_operand 3 "register_operand" "=df") | |
9894 | (call (mem (match_dup 1)) | |
9895 | (match_dup 2))) | |
9896 | (clobber (match_operand:SI 4 "register_operand" "=d"))] | |
9897 | "!TARGET_ABICALLS && !TARGET_LONG_CALLS" | |
9898 | "* | |
9899 | { | |
9900 | register rtx target = operands[1]; | |
9901 | ||
9902 | if (GET_CODE (target) == SYMBOL_REF) | |
9903 | return \"%*jal\\t%1\"; | |
9904 | else if (GET_CODE (target) == CONST_INT) | |
9905 | return \"%[li\\t%@,%1\\n\\t%*jal\\t%4,%@%]\"; | |
9906 | else | |
9907 | return \"%*jal\\t%4,%1\"; | |
9908 | }" | |
9909 | [(set_attr "type" "call") | |
9910 | (set_attr "mode" "none")]) | |
9911 | ||
bd16a708 JW |
9912 | (define_insn "call_value_multiple_internal2" |
9913 | [(set (match_operand 0 "register_operand" "=df") | |
aa4e54c4 | 9914 | (call (mem (match_operand 1 "call_insn_operand" "ri")) |
bd16a708 JW |
9915 | (match_operand 2 "" "i"))) |
9916 | (set (match_operand 3 "register_operand" "=df") | |
aa4e54c4 | 9917 | (call (mem (match_dup 1)) |
bd16a708 JW |
9918 | (match_dup 2))) |
9919 | (clobber (match_operand:SI 4 "register_operand" "=d"))] | |
9920 | "TARGET_ABICALLS && !TARGET_LONG_CALLS" | |
9921 | "* | |
9922 | { | |
aa4e54c4 | 9923 | register rtx target = operands[1]; |
bd16a708 JW |
9924 | |
9925 | if (GET_CODE (target) == SYMBOL_REF) | |
bd16a708 | 9926 | { |
5aae9091 JW |
9927 | if (GET_MODE (target) == SImode) |
9928 | return \"la\\t%^,%1\\n\\tjal\\t%4,%^\"; | |
bd16a708 | 9929 | else |
5aae9091 | 9930 | return \"la\\t%^,%1\\n\\tjal\\t%4,%^\"; |
bd16a708 | 9931 | } |
5aae9091 JW |
9932 | else if (GET_CODE (target) == CONST_INT) |
9933 | return \"li\\t%^,%1\\n\\tjal\\t%4,%^\"; | |
9934 | else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM) | |
9935 | return \"move\\t%^,%1\\n\\tjal\\t%4,%^\"; | |
9936 | else | |
9937 | return \"jal\\t%4,%1\"; | |
bd16a708 JW |
9938 | }" |
9939 | [(set_attr "type" "call") | |
9940 | (set_attr "mode" "none") | |
0ff83799 | 9941 | (set_attr "length" "8")]) |
bd16a708 JW |
9942 | |
9943 | ||
a93821e9 TW |
9944 | ;; Call subroutine returning any type. |
9945 | ||
9946 | (define_expand "untyped_call" | |
9947 | [(parallel [(call (match_operand 0 "" "") | |
9948 | (const_int 0)) | |
9949 | (match_operand 1 "" "") | |
9950 | (match_operand 2 "" "")])] | |
9951 | "" | |
9952 | " | |
9953 | { | |
740b4585 | 9954 | if (operands[0]) /* silence statement not reached warnings */ |
a93821e9 | 9955 | { |
740b4585 MM |
9956 | int i; |
9957 | ||
0499c2e4 | 9958 | emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); |
a93821e9 | 9959 | |
740b4585 MM |
9960 | for (i = 0; i < XVECLEN (operands[2], 0); i++) |
9961 | { | |
9962 | rtx set = XVECEXP (operands[2], 0, i); | |
9963 | emit_move_insn (SET_DEST (set), SET_SRC (set)); | |
9964 | } | |
a93821e9 | 9965 | |
740b4585 MM |
9966 | emit_insn (gen_blockage ()); |
9967 | DONE; | |
9968 | } | |
a93821e9 | 9969 | }") |
8ef30996 MM |
9970 | \f |
9971 | ;; | |
9972 | ;; .................... | |
9973 | ;; | |
9974 | ;; MISC. | |
9975 | ;; | |
9976 | ;; .................... | |
9977 | ;; | |
9978 | ||
9979 | (define_insn "nop" | |
9980 | [(const_int 0)] | |
9981 | "" | |
9982 | "%(nop%)" | |
9983 | [(set_attr "type" "nop") | |
0ff83799 | 9984 | (set_attr "mode" "none")]) |
8ef30996 | 9985 | |
e454beb7 ILT |
9986 | ;; The MIPS chip does not seem to require stack probes. |
9987 | ;; | |
9988 | ;; (define_expand "probe" | |
9989 | ;; [(set (match_dup 0) | |
9990 | ;; (match_dup 1))] | |
9991 | ;; "" | |
9992 | ;; " | |
9993 | ;; { | |
9994 | ;; operands[0] = gen_reg_rtx (SImode); | |
c5c76735 | 9995 | ;; operands[1] = gen_rtx_MEM (SImode, stack_pointer_rtx); |
e454beb7 ILT |
9996 | ;; MEM_VOLATILE_P (operands[1]) = TRUE; |
9997 | ;; | |
9998 | ;; /* fall through and generate default code */ | |
9999 | ;; }") | |
10000 | ;; | |
e19ff60f JW |
10001 | \f |
10002 | ;; | |
10003 | ;; MIPS4 Conditional move instructions. | |
10004 | ||
10005 | (define_insn "" | |
10006 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
10007 | (if_then_else:SI | |
10008 | (match_operator 4 "equality_op" | |
10009 | [(match_operand:SI 1 "register_operand" "d,d") | |
10010 | (const_int 0)]) | |
10011 | (match_operand:SI 2 "reg_or_0_operand" "dJ,0") | |
10012 | (match_operand:SI 3 "reg_or_0_operand" "0,dJ")))] | |
0025b7fa | 10013 | "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" |
e19ff60f JW |
10014 | "@ |
10015 | mov%B4\\t%0,%z2,%1 | |
10016 | mov%b4\\t%0,%z3,%1" | |
10017 | [(set_attr "type" "move") | |
10018 | (set_attr "mode" "SI")]) | |
10019 | ||
197b2bf3 JW |
10020 | (define_insn "" |
10021 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
10022 | (if_then_else:SI | |
10023 | (match_operator 4 "equality_op" | |
1908a152 | 10024 | [(match_operand:DI 1 "se_register_operand" "d,d") |
197b2bf3 JW |
10025 | (const_int 0)]) |
10026 | (match_operand:SI 2 "reg_or_0_operand" "dJ,0") | |
10027 | (match_operand:SI 3 "reg_or_0_operand" "0,dJ")))] | |
0025b7fa | 10028 | "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" |
197b2bf3 JW |
10029 | "@ |
10030 | mov%B4\\t%0,%z2,%1 | |
10031 | mov%b4\\t%0,%z3,%1" | |
10032 | [(set_attr "type" "move") | |
10033 | (set_attr "mode" "SI")]) | |
10034 | ||
e19ff60f JW |
10035 | (define_insn "" |
10036 | [(set (match_operand:SI 0 "register_operand" "=d,d") | |
10037 | (if_then_else:SI | |
b8eb88d0 ILT |
10038 | (match_operator 3 "equality_op" [(match_operand:CC 4 |
10039 | "register_operand" | |
10040 | "z,z") | |
10041 | (const_int 0)]) | |
e19ff60f JW |
10042 | (match_operand:SI 1 "reg_or_0_operand" "dJ,0") |
10043 | (match_operand:SI 2 "reg_or_0_operand" "0,dJ")))] | |
76ee8042 | 10044 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" |
e19ff60f | 10045 | "@ |
b8eb88d0 ILT |
10046 | mov%T3\\t%0,%z1,%4 |
10047 | mov%t3\\t%0,%z2,%4" | |
e19ff60f JW |
10048 | [(set_attr "type" "move") |
10049 | (set_attr "mode" "SI")]) | |
10050 | ||
197b2bf3 JW |
10051 | (define_insn "" |
10052 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
10053 | (if_then_else:DI | |
10054 | (match_operator 4 "equality_op" | |
10055 | [(match_operand:SI 1 "register_operand" "d,d") | |
10056 | (const_int 0)]) | |
1908a152 ILT |
10057 | (match_operand:DI 2 "se_reg_or_0_operand" "dJ,0") |
10058 | (match_operand:DI 3 "se_reg_or_0_operand" "0,dJ")))] | |
0025b7fa | 10059 | "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" |
197b2bf3 JW |
10060 | "@ |
10061 | mov%B4\\t%0,%z2,%1 | |
10062 | mov%b4\\t%0,%z3,%1" | |
10063 | [(set_attr "type" "move") | |
10064 | (set_attr "mode" "DI")]) | |
10065 | ||
e19ff60f JW |
10066 | (define_insn "" |
10067 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
10068 | (if_then_else:DI | |
10069 | (match_operator 4 "equality_op" | |
1908a152 | 10070 | [(match_operand:DI 1 "se_register_operand" "d,d") |
e19ff60f | 10071 | (const_int 0)]) |
1908a152 ILT |
10072 | (match_operand:DI 2 "se_reg_or_0_operand" "dJ,0") |
10073 | (match_operand:DI 3 "se_reg_or_0_operand" "0,dJ")))] | |
0025b7fa | 10074 | "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" |
e19ff60f JW |
10075 | "@ |
10076 | mov%B4\\t%0,%z2,%1 | |
10077 | mov%b4\\t%0,%z3,%1" | |
10078 | [(set_attr "type" "move") | |
10079 | (set_attr "mode" "DI")]) | |
10080 | ||
10081 | (define_insn "" | |
10082 | [(set (match_operand:DI 0 "register_operand" "=d,d") | |
10083 | (if_then_else:DI | |
b8eb88d0 ILT |
10084 | (match_operator 3 "equality_op" [(match_operand:CC 4 |
10085 | "register_operand" | |
10086 | "z,z") | |
10087 | (const_int 0)]) | |
1908a152 ILT |
10088 | (match_operand:DI 1 "se_reg_or_0_operand" "dJ,0") |
10089 | (match_operand:DI 2 "se_reg_or_0_operand" "0,dJ")))] | |
76ee8042 | 10090 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" |
e19ff60f | 10091 | "@ |
b8eb88d0 ILT |
10092 | mov%T3\\t%0,%z1,%4 |
10093 | mov%t3\\t%0,%z2,%4" | |
e19ff60f JW |
10094 | [(set_attr "type" "move") |
10095 | (set_attr "mode" "DI")]) | |
10096 | ||
10097 | (define_insn "" | |
10098 | [(set (match_operand:SF 0 "register_operand" "=f,f") | |
10099 | (if_then_else:SF | |
10100 | (match_operator 4 "equality_op" | |
10101 | [(match_operand:SI 1 "register_operand" "d,d") | |
10102 | (const_int 0)]) | |
10103 | (match_operand:SF 2 "register_operand" "f,0") | |
10104 | (match_operand:SF 3 "register_operand" "0,f")))] | |
76ee8042 | 10105 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" |
e19ff60f JW |
10106 | "@ |
10107 | mov%B4.s\\t%0,%2,%1 | |
10108 | mov%b4.s\\t%0,%3,%1" | |
10109 | [(set_attr "type" "move") | |
10110 | (set_attr "mode" "SF")]) | |
10111 | ||
b3a79892 MM |
10112 | (define_insn "" |
10113 | [(set (match_operand:SF 0 "register_operand" "=f,f") | |
10114 | (if_then_else:SF | |
10115 | (match_operator 4 "equality_op" | |
10116 | [(match_operand:DI 1 "se_register_operand" "d,d") | |
10117 | (const_int 0)]) | |
10118 | (match_operand:SF 2 "register_operand" "f,0") | |
10119 | (match_operand:SF 3 "register_operand" "0,f")))] | |
76ee8042 | 10120 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" |
b3a79892 MM |
10121 | "@ |
10122 | mov%B4.s\\t%0,%2,%1 | |
10123 | mov%b4.s\\t%0,%3,%1" | |
10124 | [(set_attr "type" "move") | |
10125 | (set_attr "mode" "SF")]) | |
10126 | ||
e19ff60f JW |
10127 | (define_insn "" |
10128 | [(set (match_operand:SF 0 "register_operand" "=f,f") | |
10129 | (if_then_else:SF | |
b8eb88d0 ILT |
10130 | (match_operator 3 "equality_op" [(match_operand:CC 4 |
10131 | "register_operand" | |
10132 | "z,z") | |
10133 | (const_int 0)]) | |
e19ff60f JW |
10134 | (match_operand:SF 1 "register_operand" "f,0") |
10135 | (match_operand:SF 2 "register_operand" "0,f")))] | |
76ee8042 | 10136 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" |
e19ff60f | 10137 | "@ |
b8eb88d0 ILT |
10138 | mov%T3.s\\t%0,%1,%4 |
10139 | mov%t3.s\\t%0,%2,%4" | |
e19ff60f JW |
10140 | [(set_attr "type" "move") |
10141 | (set_attr "mode" "SF")]) | |
10142 | ||
10143 | (define_insn "" | |
10144 | [(set (match_operand:DF 0 "register_operand" "=f,f") | |
10145 | (if_then_else:DF | |
10146 | (match_operator 4 "equality_op" | |
10147 | [(match_operand:SI 1 "register_operand" "d,d") | |
10148 | (const_int 0)]) | |
10149 | (match_operand:DF 2 "register_operand" "f,0") | |
10150 | (match_operand:DF 3 "register_operand" "0,f")))] | |
76ee8042 | 10151 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
b3a79892 MM |
10152 | "@ |
10153 | mov%B4.d\\t%0,%2,%1 | |
10154 | mov%b4.d\\t%0,%3,%1" | |
10155 | [(set_attr "type" "move") | |
10156 | (set_attr "mode" "DF")]) | |
10157 | ||
10158 | (define_insn "" | |
10159 | [(set (match_operand:DF 0 "register_operand" "=f,f") | |
10160 | (if_then_else:DF | |
10161 | (match_operator 4 "equality_op" | |
10162 | [(match_operand:DI 1 "se_register_operand" "d,d") | |
10163 | (const_int 0)]) | |
10164 | (match_operand:DF 2 "register_operand" "f,0") | |
10165 | (match_operand:DF 3 "register_operand" "0,f")))] | |
76ee8042 | 10166 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
e19ff60f JW |
10167 | "@ |
10168 | mov%B4.d\\t%0,%2,%1 | |
10169 | mov%b4.d\\t%0,%3,%1" | |
10170 | [(set_attr "type" "move") | |
10171 | (set_attr "mode" "DF")]) | |
10172 | ||
10173 | (define_insn "" | |
10174 | [(set (match_operand:DF 0 "register_operand" "=f,f") | |
10175 | (if_then_else:DF | |
b8eb88d0 ILT |
10176 | (match_operator 3 "equality_op" [(match_operand:CC 4 |
10177 | "register_operand" | |
10178 | "z,z") | |
10179 | (const_int 0)]) | |
e19ff60f JW |
10180 | (match_operand:DF 1 "register_operand" "f,0") |
10181 | (match_operand:DF 2 "register_operand" "0,f")))] | |
76ee8042 | 10182 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
e19ff60f | 10183 | "@ |
b8eb88d0 ILT |
10184 | mov%T3.d\\t%0,%1,%4 |
10185 | mov%t3.d\\t%0,%2,%4" | |
e19ff60f JW |
10186 | [(set_attr "type" "move") |
10187 | (set_attr "mode" "DF")]) | |
10188 | ||
10189 | ;; These are the main define_expand's used to make conditional moves. | |
10190 | ||
10191 | (define_expand "movsicc" | |
10192 | [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) | |
10193 | (set (match_operand:SI 0 "register_operand" "") | |
10194 | (if_then_else:SI (match_dup 5) | |
10195 | (match_operand:SI 2 "reg_or_0_operand" "") | |
10196 | (match_operand:SI 3 "reg_or_0_operand" "")))] | |
0025b7fa | 10197 | "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" |
e19ff60f JW |
10198 | " |
10199 | { | |
b8eb88d0 ILT |
10200 | gen_conditional_move (operands); |
10201 | DONE; | |
10202 | }") | |
e19ff60f | 10203 | |
b8eb88d0 ILT |
10204 | (define_expand "movdicc" |
10205 | [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) | |
10206 | (set (match_operand:DI 0 "register_operand" "") | |
10207 | (if_then_else:DI (match_dup 5) | |
1908a152 ILT |
10208 | (match_operand:DI 2 "se_reg_or_0_operand" "") |
10209 | (match_operand:DI 3 "se_reg_or_0_operand" "")))] | |
0025b7fa | 10210 | "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" |
b8eb88d0 ILT |
10211 | " |
10212 | { | |
10213 | gen_conditional_move (operands); | |
10214 | DONE; | |
10215 | }") | |
e19ff60f | 10216 | |
b8eb88d0 ILT |
10217 | (define_expand "movsfcc" |
10218 | [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) | |
10219 | (set (match_operand:SF 0 "register_operand" "") | |
10220 | (if_then_else:SF (match_dup 5) | |
91760fce ILT |
10221 | (match_operand:SF 2 "register_operand" "") |
10222 | (match_operand:SF 3 "register_operand" "")))] | |
76ee8042 | 10223 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" |
b8eb88d0 ILT |
10224 | " |
10225 | { | |
10226 | gen_conditional_move (operands); | |
10227 | DONE; | |
e19ff60f JW |
10228 | }") |
10229 | ||
b8eb88d0 ILT |
10230 | (define_expand "movdfcc" |
10231 | [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) | |
10232 | (set (match_operand:DF 0 "register_operand" "") | |
10233 | (if_then_else:DF (match_dup 5) | |
91760fce ILT |
10234 | (match_operand:DF 2 "register_operand" "") |
10235 | (match_operand:DF 3 "register_operand" "")))] | |
76ee8042 | 10236 | "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" |
b8eb88d0 ILT |
10237 | " |
10238 | { | |
10239 | gen_conditional_move (operands); | |
10240 | DONE; | |
10241 | }") | |
2bcb2ab3 GK |
10242 | \f |
10243 | ;; | |
10244 | ;; .................... | |
10245 | ;; | |
10246 | ;; mips16 inline constant tables | |
10247 | ;; | |
10248 | ;; .................... | |
10249 | ;; | |
10250 | ||
10251 | (define_insn "consttable_qi" | |
10252 | [(unspec_volatile [(match_operand:QI 0 "consttable_operand" "=g")] 10)] | |
10253 | "TARGET_MIPS16" | |
10254 | "* | |
10255 | { | |
10256 | assemble_integer (operands[0], 1, 1); | |
10257 | return \"\"; | |
10258 | }" | |
10259 | [(set_attr "type" "unknown") | |
10260 | (set_attr "mode" "QI") | |
0ff83799 | 10261 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10262 | |
10263 | (define_insn "consttable_hi" | |
10264 | [(unspec_volatile [(match_operand:HI 0 "consttable_operand" "=g")] 11)] | |
10265 | "TARGET_MIPS16" | |
10266 | "* | |
10267 | { | |
10268 | assemble_integer (operands[0], 2, 1); | |
10269 | return \"\"; | |
10270 | }" | |
10271 | [(set_attr "type" "unknown") | |
10272 | (set_attr "mode" "HI") | |
0ff83799 | 10273 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10274 | |
10275 | (define_insn "consttable_si" | |
10276 | [(unspec_volatile [(match_operand:SI 0 "consttable_operand" "=g")] 12)] | |
10277 | "TARGET_MIPS16" | |
10278 | "* | |
10279 | { | |
10280 | assemble_integer (operands[0], 4, 1); | |
10281 | return \"\"; | |
10282 | }" | |
10283 | [(set_attr "type" "unknown") | |
10284 | (set_attr "mode" "SI") | |
0ff83799 | 10285 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10286 | |
10287 | (define_insn "consttable_di" | |
10288 | [(unspec_volatile [(match_operand:DI 0 "consttable_operand" "=g")] 13)] | |
10289 | "TARGET_MIPS16" | |
10290 | "* | |
10291 | { | |
10292 | assemble_integer (operands[0], 8, 1); | |
10293 | return \"\"; | |
10294 | }" | |
10295 | [(set_attr "type" "unknown") | |
10296 | (set_attr "mode" "DI") | |
0ff83799 | 10297 | (set_attr "length" "16")]) |
2bcb2ab3 GK |
10298 | |
10299 | (define_insn "consttable_sf" | |
10300 | [(unspec_volatile [(match_operand:SF 0 "consttable_operand" "=g")] 14)] | |
10301 | "TARGET_MIPS16" | |
10302 | "* | |
10303 | { | |
10304 | union real_extract u; | |
10305 | ||
10306 | if (GET_CODE (operands[0]) != CONST_DOUBLE) | |
10307 | abort (); | |
4e135bdd | 10308 | memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u); |
2bcb2ab3 GK |
10309 | assemble_real (u.d, SFmode); |
10310 | return \"\"; | |
10311 | }" | |
10312 | [(set_attr "type" "unknown") | |
10313 | (set_attr "mode" "SF") | |
0ff83799 | 10314 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10315 | |
10316 | (define_insn "consttable_df" | |
10317 | [(unspec_volatile [(match_operand:DF 0 "consttable_operand" "=g")] 15)] | |
10318 | "TARGET_MIPS16" | |
10319 | "* | |
10320 | { | |
10321 | union real_extract u; | |
10322 | ||
10323 | if (GET_CODE (operands[0]) != CONST_DOUBLE) | |
10324 | abort (); | |
4e135bdd | 10325 | memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u); |
2bcb2ab3 GK |
10326 | assemble_real (u.d, DFmode); |
10327 | return \"\"; | |
10328 | }" | |
10329 | [(set_attr "type" "unknown") | |
10330 | (set_attr "mode" "DF") | |
0ff83799 | 10331 | (set_attr "length" "16")]) |
2bcb2ab3 GK |
10332 | |
10333 | (define_insn "align_2" | |
10334 | [(unspec_volatile [(const_int 0)] 16)] | |
10335 | "TARGET_MIPS16" | |
10336 | ".align 1" | |
10337 | [(set_attr "type" "unknown") | |
10338 | (set_attr "mode" "HI") | |
0ff83799 | 10339 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10340 | |
10341 | (define_insn "align_4" | |
10342 | [(unspec_volatile [(const_int 0)] 17)] | |
10343 | "TARGET_MIPS16" | |
10344 | ".align 2" | |
10345 | [(set_attr "type" "unknown") | |
10346 | (set_attr "mode" "SI") | |
0ff83799 | 10347 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10348 | |
10349 | (define_insn "align_8" | |
10350 | [(unspec_volatile [(const_int 0)] 18)] | |
10351 | "TARGET_MIPS16" | |
10352 | ".align 3" | |
10353 | [(set_attr "type" "unknown") | |
10354 | (set_attr "mode" "DI") | |
0ff83799 | 10355 | (set_attr "length" "12")]) |
2bcb2ab3 GK |
10356 | \f |
10357 | ;; | |
10358 | ;; .................... | |
10359 | ;; | |
10360 | ;; mips16 peepholes | |
10361 | ;; | |
10362 | ;; .................... | |
10363 | ;; | |
10364 | ||
10365 | ;; On the mips16, reload will sometimes decide that a pseudo register | |
10366 | ;; should go into $24, and then later on have to reload that register. | |
10367 | ;; When that happens, we get a load of a general register followed by | |
10368 | ;; a move from the general register to $24 followed by a branch. | |
10369 | ;; These peepholes catch the common case, and fix it to just use the | |
10370 | ;; general register for the branch. | |
10371 | ||
10372 | (define_peephole | |
10373 | [(set (match_operand:SI 0 "register_operand" "=t") | |
10374 | (match_operand:SI 1 "register_operand" "d")) | |
10375 | (set (pc) | |
10376 | (if_then_else (match_operator:SI 2 "equality_op" [(match_dup 0) | |
10377 | (const_int 0)]) | |
10378 | (match_operand 3 "pc_or_label_operand" "") | |
10379 | (match_operand 4 "pc_or_label_operand" "")))] | |
10380 | "TARGET_MIPS16 | |
10381 | && GET_CODE (operands[0]) == REG | |
10382 | && REGNO (operands[0]) == 24 | |
10383 | && dead_or_set_p (insn, operands[0]) | |
10384 | && GET_CODE (operands[1]) == REG | |
10385 | && M16_REG_P (REGNO (operands[1]))" | |
10386 | "* | |
10387 | { | |
10388 | if (operands[3] != pc_rtx) | |
10389 | return \"%*b%C2z\\t%1,%3\"; | |
10390 | else | |
10391 | return \"%*b%N2z\\t%1,%4\"; | |
10392 | }" | |
10393 | [(set_attr "type" "branch") | |
10394 | (set_attr "mode" "none") | |
0ff83799 | 10395 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10396 | |
10397 | (define_peephole | |
10398 | [(set (match_operand:DI 0 "register_operand" "=t") | |
10399 | (match_operand:DI 1 "register_operand" "d")) | |
10400 | (set (pc) | |
10401 | (if_then_else (match_operator:DI 2 "equality_op" [(match_dup 0) | |
10402 | (const_int 0)]) | |
10403 | (match_operand 3 "pc_or_label_operand" "") | |
10404 | (match_operand 4 "pc_or_label_operand" "")))] | |
10405 | "TARGET_MIPS16 && TARGET_64BIT | |
10406 | && GET_CODE (operands[0]) == REG | |
10407 | && REGNO (operands[0]) == 24 | |
10408 | && dead_or_set_p (insn, operands[0]) | |
10409 | && GET_CODE (operands[1]) == REG | |
10410 | && M16_REG_P (REGNO (operands[1]))" | |
10411 | "* | |
10412 | { | |
10413 | if (operands[3] != pc_rtx) | |
10414 | return \"%*b%C2z\\t%1,%3\"; | |
10415 | else | |
10416 | return \"%*b%N2z\\t%1,%4\"; | |
10417 | }" | |
10418 | [(set_attr "type" "branch") | |
10419 | (set_attr "mode" "none") | |
0ff83799 | 10420 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10421 | |
10422 | ;; We can also have the reverse reload: reload will spill $24 into | |
10423 | ;; another register, and then do a branch on that register when it | |
10424 | ;; could have just stuck with $24. | |
10425 | ||
10426 | (define_peephole | |
10427 | [(set (match_operand:SI 0 "register_operand" "=d") | |
10428 | (match_operand:SI 1 "register_operand" "t")) | |
10429 | (set (pc) | |
10430 | (if_then_else (match_operator:SI 2 "equality_op" [(match_dup 0) | |
10431 | (const_int 0)]) | |
10432 | (match_operand 3 "pc_or_label_operand" "") | |
10433 | (match_operand 4 "pc_or_label_operand" "")))] | |
10434 | "TARGET_MIPS16 | |
10435 | && GET_CODE (operands[1]) == REG | |
10436 | && REGNO (operands[1]) == 24 | |
10437 | && GET_CODE (operands[0]) == REG | |
10438 | && M16_REG_P (REGNO (operands[0])) | |
10439 | && dead_or_set_p (insn, operands[0])" | |
10440 | "* | |
10441 | { | |
10442 | if (operands[3] != pc_rtx) | |
10443 | return \"%*bt%C2z\\t%3\"; | |
10444 | else | |
10445 | return \"%*bt%N2z\\t%4\"; | |
10446 | }" | |
10447 | [(set_attr "type" "branch") | |
10448 | (set_attr "mode" "none") | |
0ff83799 | 10449 | (set_attr "length" "8")]) |
2bcb2ab3 GK |
10450 | |
10451 | (define_peephole | |
10452 | [(set (match_operand:DI 0 "register_operand" "=d") | |
10453 | (match_operand:DI 1 "register_operand" "t")) | |
10454 | (set (pc) | |
10455 | (if_then_else (match_operator:DI 2 "equality_op" [(match_dup 0) | |
10456 | (const_int 0)]) | |
10457 | (match_operand 3 "pc_or_label_operand" "") | |
10458 | (match_operand 4 "pc_or_label_operand" "")))] | |
10459 | "TARGET_MIPS16 && TARGET_64BIT | |
10460 | && GET_CODE (operands[1]) == REG | |
10461 | && REGNO (operands[1]) == 24 | |
10462 | && GET_CODE (operands[0]) == REG | |
10463 | && M16_REG_P (REGNO (operands[0])) | |
10464 | && dead_or_set_p (insn, operands[0])" | |
10465 | "* | |
10466 | { | |
10467 | if (operands[3] != pc_rtx) | |
10468 | return \"%*bt%C2z\\t%3\"; | |
10469 | else | |
10470 | return \"%*bt%N2z\\t%4\"; | |
10471 | }" | |
10472 | [(set_attr "type" "branch") | |
10473 | (set_attr "mode" "none") | |
0ff83799 | 10474 | (set_attr "length" "8")]) |
be8b493b JL |
10475 | |
10476 | ;; For the rare case where we need to load an address into a register | |
10477 | ;; that can not be recognized by the normal movsi/addsi instructions. | |
10478 | ;; I have no idea how many insns this can actually generate. It should | |
10479 | ;; be rare, so over-estimating as 10 instructions should not have any | |
10480 | ;; real performance impact. | |
10481 | (define_insn "leasi" | |
10482 | [(set (match_operand:SI 0 "register_operand" "=d") | |
10483 | (match_operand:SI 1 "address_operand" "p"))] | |
10484 | "Pmode == SImode" | |
10485 | "la %0,%a1" | |
10486 | [(set_attr "type" "arith") | |
10487 | (set_attr "mode" "SI") | |
10488 | (set_attr "length" "40")]) | |
10489 | ||
10490 | ;; Similarly for targets where we have 64bit pointers. | |
10491 | (define_insn "leadi" | |
10492 | [(set (match_operand:DI 0 "register_operand" "=d") | |
10493 | (match_operand:DI 1 "address_operand" "p"))] | |
10494 | "Pmode == DImode" | |
10495 | "la %0,%a1" | |
10496 | [(set_attr "type" "arith") | |
10497 | (set_attr "mode" "DI") | |
10498 | (set_attr "length" "40")]) |