]>
Commit | Line | Data |
---|---|---|
c733e074 | 1 | ;;- Machine description for HP PA-RISC architecture for GNU C compiler |
e9a25f70 | 2 | ;; Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. |
c733e074 | 3 | ;; Contributed by the Center for Software Science at the University |
876662ef | 4 | ;; of Utah. |
c733e074 TM |
5 | |
6 | ;; This file is part of GNU CC. | |
7 | ||
8 | ;; GNU CC is free software; you can redistribute it and/or modify | |
9 | ;; it under the terms of the GNU General Public License as published by | |
10 | ;; the Free Software Foundation; either version 2, or (at your option) | |
11 | ;; any later version. | |
12 | ||
13 | ;; GNU CC is distributed in the hope that it will be useful, | |
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | ;; GNU General Public License for more details. | |
17 | ||
18 | ;; You should have received a copy of the GNU General Public License | |
19 | ;; along with GNU CC; see the file COPYING. If not, write to | |
3f63df56 RK |
20 | ;; the Free Software Foundation, 59 Temple Place - Suite 330, |
21 | ;; Boston, MA 02111-1307, USA. | |
c733e074 TM |
22 | |
23 | ;; This gcc Version 2 machine description is inspired by sparc.md and | |
24 | ;; mips.md. | |
25 | ||
26 | ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
27 | ||
28 | ;; Insn type. Used to default other attribute values. | |
29 | ||
30 | ;; type "unary" insns have one input operand (1) and one output operand (0) | |
31 | ;; type "binary" insns have two input operands (1,2) and one output (0) | |
32 | ||
33 | (define_attr "type" | |
b1092901 | 34 | "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,parallel_branch" |
c733e074 TM |
35 | (const_string "binary")) |
36 | ||
c4bb6b38 JL |
37 | (define_attr "pa_combine_type" |
38 | "fmpy,faddsub,uncond_branch,addmove,none" | |
39 | (const_string "none")) | |
40 | ||
c47decad JL |
41 | ;; Processor type (for scheduling, not code generation) -- this attribute |
42 | ;; must exactly match the processor_type enumeration in pa.h. | |
43 | ;; | |
44 | ;; FIXME: Add 800 scheduling for completeness? | |
45 | ||
2da05a5b | 46 | (define_attr "cpu" "700,7100,7100LC,7200" (const (symbol_ref "pa_cpu_attr"))) |
c47decad | 47 | |
c733e074 TM |
48 | ;; Length (in # of insns). |
49 | (define_attr "length" "" | |
50 | (cond [(eq_attr "type" "load,fpload") | |
51 | (if_then_else (match_operand 1 "symbolic_memory_operand" "") | |
4c2164b7 | 52 | (const_int 8) (const_int 4)) |
c733e074 TM |
53 | |
54 | (eq_attr "type" "store,fpstore") | |
55 | (if_then_else (match_operand 0 "symbolic_memory_operand" "") | |
4c2164b7 | 56 | (const_int 8) (const_int 4)) |
c733e074 | 57 | |
c47decad | 58 | (eq_attr "type" "binary,shift,nullshift") |
c733e074 | 59 | (if_then_else (match_operand 2 "arith_operand" "") |
4c2164b7 | 60 | (const_int 4) (const_int 12)) |
c733e074 | 61 | |
c47decad | 62 | (eq_attr "type" "move,unary,shift,nullshift") |
c733e074 | 63 | (if_then_else (match_operand 1 "arith_operand" "") |
4c2164b7 | 64 | (const_int 4) (const_int 8))] |
c733e074 | 65 | |
4c2164b7 | 66 | (const_int 4))) |
c733e074 TM |
67 | |
68 | (define_asm_attributes | |
4c2164b7 | 69 | [(set_attr "length" "4") |
c733e074 TM |
70 | (set_attr "type" "multi")]) |
71 | ||
72 | ;; Attributes for instruction and branch scheduling | |
73 | ||
f854c12c | 74 | ;; For conditional branches. |
3bf1c6b5 | 75 | (define_attr "in_branch_delay" "false,true" |
b1092901 | 76 | (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch") |
4c2164b7 | 77 | (eq_attr "length" "4")) |
3bf1c6b5 JL |
78 | (const_string "true") |
79 | (const_string "false"))) | |
c733e074 | 80 | |
99457156 JL |
81 | ;; Disallow instructions which use the FPU since they will tie up the FPU |
82 | ;; even if the instruction is nullified. | |
83 | (define_attr "in_nullified_branch_delay" "false,true" | |
b1092901 | 84 | (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch") |
4c2164b7 | 85 | (eq_attr "length" "4")) |
99457156 JL |
86 | (const_string "true") |
87 | (const_string "false"))) | |
88 | ||
2f95ebc2 | 89 | ;; For calls and millicode calls. Allow unconditional branches in the |
f854c12c JL |
90 | ;; delay slot. |
91 | (define_attr "in_call_delay" "false,true" | |
b1092901 | 92 | (cond [(and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch") |
f854c12c JL |
93 | (eq_attr "length" "4")) |
94 | (const_string "true") | |
95 | (eq_attr "type" "uncond_branch") | |
96 | (if_then_else (ne (symbol_ref "TARGET_JUMP_IN_DELAY") | |
97 | (const_int 0)) | |
98 | (const_string "true") | |
99 | (const_string "false"))] | |
100 | (const_string "false"))) | |
f854c12c JL |
101 | |
102 | ||
b1092901 | 103 | ;; Call delay slot description. |
c4bb6b38 | 104 | (define_delay (eq_attr "type" "call") |
f854c12c JL |
105 | [(eq_attr "in_call_delay" "true") (nil) (nil)]) |
106 | ||
f726ea7d | 107 | ;; millicode call delay slot description. Note it disallows delay slot |
b1092901 | 108 | ;; when TARGET_PORTABLE_RUNTIME is true. |
f726ea7d JL |
109 | (define_delay (eq_attr "type" "milli") |
110 | [(and (eq_attr "in_call_delay" "true") | |
2e742d89 | 111 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))) |
f726ea7d JL |
112 | (nil) (nil)]) |
113 | ||
b1092901 JL |
114 | ;; Return and other similar instructions. |
115 | (define_delay (eq_attr "type" "branch,parallel_branch") | |
3bf1c6b5 | 116 | [(eq_attr "in_branch_delay" "true") (nil) (nil)]) |
c733e074 | 117 | |
99457156 | 118 | ;; Floating point conditional branch delay slot description and |
e9cfad81 | 119 | (define_delay (eq_attr "type" "fbranch") |
876662ef | 120 | [(eq_attr "in_branch_delay" "true") |
99457156 | 121 | (eq_attr "in_nullified_branch_delay" "true") |
e9cfad81 | 122 | (nil)]) |
c733e074 | 123 | |
e9cfad81 | 124 | ;; Integer conditional branch delay slot description. |
99457156 | 125 | ;; Nullification of conditional branches on the PA is dependent on the |
f65590a9 JL |
126 | ;; direction of the branch. Forward branches nullify true and |
127 | ;; backward branches nullify false. If the direction is unknown | |
128 | ;; then nullification is not allowed. | |
e9cfad81 | 129 | (define_delay (eq_attr "type" "cbranch") |
2f95ebc2 TG |
130 | [(eq_attr "in_branch_delay" "true") |
131 | (and (eq_attr "in_nullified_branch_delay" "true") | |
99457156 JL |
132 | (attr_flag "forward")) |
133 | (and (eq_attr "in_nullified_branch_delay" "true") | |
134 | (attr_flag "backward"))]) | |
c733e074 | 135 | |
c4bb6b38 JL |
136 | (define_delay (and (eq_attr "type" "uncond_branch") |
137 | (eq (symbol_ref "following_call (insn)") | |
138 | (const_int 0))) | |
139 | [(eq_attr "in_branch_delay" "true") (nil) (nil)]) | |
140 | ||
c47decad JL |
141 | ;; Function units of the HPPA. The following data is for the 700 CPUs |
142 | ;; (Mustang CPU + Timex FPU aka PA-89) because that's what I have the docs for. | |
c733e074 TM |
143 | ;; Scheduling instructions for PA-83 machines according to the Snake |
144 | ;; constraints shouldn't hurt. | |
145 | ||
146 | ;; (define_function_unit {name} {num-units} {n-users} {test} | |
c8e18a2b | 147 | ;; {ready-delay} {issue-delay} [{conflict-list}]) |
c733e074 TM |
148 | |
149 | ;; The integer ALU. | |
150 | ;; (Noted only for documentation; units that take one cycle do not need to | |
151 | ;; be specified.) | |
152 | ||
153 | ;; (define_function_unit "alu" 1 0 | |
c47decad JL |
154 | ;; (and (eq_attr "type" "unary,shift,nullshift,binary,move,address") |
155 | ;; (eq_attr "cpu" "700")) | |
156 | ;; 1 0) | |
c733e074 TM |
157 | |
158 | ||
159 | ;; Memory. Disregarding Cache misses, the Mustang memory times are: | |
c47decad | 160 | ;; load: 2, fpload: 3 |
c733e074 | 161 | ;; store, fpstore: 3, no D-cache operations should be scheduled. |
c733e074 | 162 | |
c47decad JL |
163 | (define_function_unit "pa700memory" 1 0 |
164 | (and (eq_attr "type" "load,fpload") | |
165 | (eq_attr "cpu" "700")) 2 0) | |
166 | (define_function_unit "pa700memory" 1 0 | |
167 | (and (eq_attr "type" "store,fpstore") | |
168 | (eq_attr "cpu" "700")) 3 3) | |
c733e074 | 169 | |
c47decad | 170 | ;; The Timex (aka 700) has two floating-point units: ALU, and MUL/DIV/SQRT. |
c733e074 TM |
171 | ;; Timings: |
172 | ;; Instruction Time Unit Minimum Distance (unit contention) | |
173 | ;; fcpy 3 ALU 2 | |
174 | ;; fabs 3 ALU 2 | |
175 | ;; fadd 3 ALU 2 | |
176 | ;; fsub 3 ALU 2 | |
177 | ;; fcmp 3 ALU 2 | |
178 | ;; fcnv 3 ALU 2 | |
179 | ;; fmpyadd 3 ALU,MPY 2 | |
180 | ;; fmpysub 3 ALU,MPY 2 | |
181 | ;; fmpycfxt 3 ALU,MPY 2 | |
182 | ;; fmpy 3 MPY 2 | |
183 | ;; fmpyi 3 MPY 2 | |
184 | ;; fdiv,sgl 10 MPY 10 | |
185 | ;; fdiv,dbl 12 MPY 12 | |
186 | ;; fsqrt,sgl 14 MPY 14 | |
187 | ;; fsqrt,dbl 18 MPY 18 | |
188 | ||
c47decad JL |
189 | (define_function_unit "pa700fp_alu" 1 0 |
190 | (and (eq_attr "type" "fpcc") | |
191 | (eq_attr "cpu" "700")) 4 2) | |
192 | (define_function_unit "pa700fp_alu" 1 0 | |
193 | (and (eq_attr "type" "fpalu") | |
194 | (eq_attr "cpu" "700")) 3 2) | |
195 | (define_function_unit "pa700fp_mpy" 1 0 | |
196 | (and (eq_attr "type" "fpmulsgl,fpmuldbl") | |
197 | (eq_attr "cpu" "700")) 3 2) | |
198 | (define_function_unit "pa700fp_mpy" 1 0 | |
199 | (and (eq_attr "type" "fpdivsgl") | |
200 | (eq_attr "cpu" "700")) 10 10) | |
201 | (define_function_unit "pa700fp_mpy" 1 0 | |
202 | (and (eq_attr "type" "fpdivdbl") | |
203 | (eq_attr "cpu" "700")) 12 12) | |
204 | (define_function_unit "pa700fp_mpy" 1 0 | |
205 | (and (eq_attr "type" "fpsqrtsgl") | |
206 | (eq_attr "cpu" "700")) 14 14) | |
207 | (define_function_unit "pa700fp_mpy" 1 0 | |
208 | (and (eq_attr "type" "fpsqrtdbl") | |
209 | (eq_attr "cpu" "700")) 18 18) | |
210 | ||
211 | ;; Function units for the 7100 and 7150. The 7100/7150 can dual-issue | |
212 | ;; floating point computations with non-floating point computations (fp loads | |
213 | ;; and stores are not fp computations). | |
214 | ;; | |
c47decad JL |
215 | |
216 | ;; Memory. Disregarding Cache misses, memory loads take two cycles; stores also | |
217 | ;; take two cycles, during which no Dcache operations should be scheduled. | |
218 | ;; Any special cases are handled in pa_adjust_cost. The 7100, 7150 and 7100LC | |
219 | ;; all have the same memory characteristics if one disregards cache misses. | |
220 | (define_function_unit "pa7100memory" 1 0 | |
221 | (and (eq_attr "type" "load,fpload") | |
2da05a5b | 222 | (eq_attr "cpu" "7100,7100LC")) 2 0) |
c47decad JL |
223 | (define_function_unit "pa7100memory" 1 0 |
224 | (and (eq_attr "type" "store,fpstore") | |
2da05a5b | 225 | (eq_attr "cpu" "7100,7100LC")) 2 2) |
c47decad JL |
226 | |
227 | ;; The 7100/7150 has three floating-point units: ALU, MUL, and DIV. | |
228 | ;; Timings: | |
229 | ;; Instruction Time Unit Minimum Distance (unit contention) | |
230 | ;; fcpy 2 ALU 1 | |
231 | ;; fabs 2 ALU 1 | |
232 | ;; fadd 2 ALU 1 | |
233 | ;; fsub 2 ALU 1 | |
234 | ;; fcmp 2 ALU 1 | |
235 | ;; fcnv 2 ALU 1 | |
236 | ;; fmpyadd 2 ALU,MPY 1 | |
237 | ;; fmpysub 2 ALU,MPY 1 | |
238 | ;; fmpycfxt 2 ALU,MPY 1 | |
239 | ;; fmpy 2 MPY 1 | |
240 | ;; fmpyi 2 MPY 1 | |
241 | ;; fdiv,sgl 8 DIV 8 | |
242 | ;; fdiv,dbl 15 DIV 15 | |
243 | ;; fsqrt,sgl 8 DIV 8 | |
244 | ;; fsqrt,dbl 15 DIV 15 | |
245 | ||
246 | (define_function_unit "pa7100fp_alu" 1 0 | |
247 | (and (eq_attr "type" "fpcc,fpalu") | |
2da05a5b | 248 | (eq_attr "cpu" "7100")) 2 1) |
c47decad JL |
249 | (define_function_unit "pa7100fp_mpy" 1 0 |
250 | (and (eq_attr "type" "fpmulsgl,fpmuldbl") | |
2da05a5b | 251 | (eq_attr "cpu" "7100")) 2 1) |
c47decad JL |
252 | (define_function_unit "pa7100fp_div" 1 0 |
253 | (and (eq_attr "type" "fpdivsgl,fpsqrtsgl") | |
2da05a5b | 254 | (eq_attr "cpu" "7100")) 8 8) |
c47decad JL |
255 | (define_function_unit "pa7100fp_div" 1 0 |
256 | (and (eq_attr "type" "fpdivdbl,fpsqrtdbl") | |
2da05a5b | 257 | (eq_attr "cpu" "7100")) 15 15) |
c47decad JL |
258 | |
259 | ;; To encourage dual issue we define function units corresponding to | |
260 | ;; the instructions which can be dual issued. This is a rather crude | |
261 | ;; approximation, the "pa7100nonflop" test in particular could be refined. | |
262 | (define_function_unit "pa7100flop" 1 1 | |
263 | (and | |
264 | (eq_attr "type" "fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl") | |
2da05a5b | 265 | (eq_attr "cpu" "7100")) 1 1) |
c47decad JL |
266 | |
267 | (define_function_unit "pa7100nonflop" 1 1 | |
268 | (and | |
269 | (eq_attr "type" "!fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl") | |
2da05a5b | 270 | (eq_attr "cpu" "7100")) 1 1) |
c47decad JL |
271 | |
272 | ||
273 | ;; Memory subsystem works just like 7100/7150 (except for cache miss times which | |
274 | ;; we don't model here). | |
275 | ||
276 | ;; The 7100LC has three floating-point units: ALU, MUL, and DIV. | |
277 | ;; Note divides and sqrt flops lock the cpu until the flop is | |
278 | ;; finished. fmpy and xmpyu (fmpyi) lock the cpu for one cycle. | |
279 | ;; There's no way to avoid the penalty. | |
280 | ;; Timings: | |
281 | ;; Instruction Time Unit Minimum Distance (unit contention) | |
282 | ;; fcpy 2 ALU 1 | |
283 | ;; fabs 2 ALU 1 | |
284 | ;; fadd 2 ALU 1 | |
285 | ;; fsub 2 ALU 1 | |
286 | ;; fcmp 2 ALU 1 | |
287 | ;; fcnv 2 ALU 1 | |
288 | ;; fmpyadd,sgl 2 ALU,MPY 1 | |
289 | ;; fmpyadd,dbl 3 ALU,MPY 2 | |
290 | ;; fmpysub,sgl 2 ALU,MPY 1 | |
291 | ;; fmpysub,dbl 3 ALU,MPY 2 | |
292 | ;; fmpycfxt,sgl 2 ALU,MPY 1 | |
293 | ;; fmpycfxt,dbl 3 ALU,MPY 2 | |
294 | ;; fmpy,sgl 2 MPY 1 | |
295 | ;; fmpy,dbl 3 MPY 2 | |
296 | ;; fmpyi 3 MPY 2 | |
297 | ;; fdiv,sgl 8 DIV 8 | |
298 | ;; fdiv,dbl 15 DIV 15 | |
299 | ;; fsqrt,sgl 8 DIV 8 | |
300 | ;; fsqrt,dbl 15 DIV 15 | |
301 | ||
302 | (define_function_unit "pa7100LCfp_alu" 1 0 | |
303 | (and (eq_attr "type" "fpcc,fpalu") | |
2da05a5b | 304 | (eq_attr "cpu" "7100LC,7200")) 2 1) |
c47decad JL |
305 | (define_function_unit "pa7100LCfp_mpy" 1 0 |
306 | (and (eq_attr "type" "fpmulsgl") | |
2da05a5b | 307 | (eq_attr "cpu" "7100LC,7200")) 2 1) |
c47decad JL |
308 | (define_function_unit "pa7100LCfp_mpy" 1 0 |
309 | (and (eq_attr "type" "fpmuldbl") | |
2da05a5b | 310 | (eq_attr "cpu" "7100LC,7200")) 3 2) |
c47decad JL |
311 | (define_function_unit "pa7100LCfp_div" 1 0 |
312 | (and (eq_attr "type" "fpdivsgl,fpsqrtsgl") | |
2da05a5b | 313 | (eq_attr "cpu" "7100LC,7200")) 8 8) |
c47decad JL |
314 | (define_function_unit "pa7100LCfp_div" 1 0 |
315 | (and (eq_attr "type" "fpdivdbl,fpsqrtdbl") | |
2da05a5b | 316 | (eq_attr "cpu" "7100LC,7200")) 15 15) |
c47decad JL |
317 | |
318 | ;; Define the various functional units for dual-issue. | |
c47decad | 319 | |
2da05a5b JL |
320 | ;; There's only one floating point unit. |
321 | (define_function_unit "pa7100LCflop" 1 1 | |
c47decad | 322 | (and |
2da05a5b JL |
323 | (eq_attr "type" "fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl") |
324 | (eq_attr "cpu" "7100LC,7200")) 1 1) | |
c47decad | 325 | |
2da05a5b JL |
326 | ;; Shifts and memory ops actually execute in one of the integer |
327 | ;; ALUs, but we can't really model that. | |
328 | (define_function_unit "pa7100LCshiftmem" 1 1 | |
c47decad | 329 | (and |
2da05a5b JL |
330 | (eq_attr "type" "shift,nullshift,load,fpload,store,fpstore") |
331 | (eq_attr "cpu" "7100LC,7200")) 1 1) | |
c47decad | 332 | |
2da05a5b JL |
333 | ;; We have two basic ALUs. |
334 | (define_function_unit "pa7100LCalu" 2 2 | |
c47decad | 335 | (and |
2da05a5b JL |
336 | (eq_attr "type" "!fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl,load,fpload,store,fpstore,shift,nullshift") |
337 | (eq_attr "cpu" "7100LC,7200")) 1 1) | |
338 | ||
339 | ;; I don't have complete information on the PA7200; however, most of | |
340 | ;; what I've heard makes it look like a 7100LC without the store-store | |
341 | ;; penalty. So that's how we'll model it. | |
342 | ||
343 | ;; Memory. Disregarding Cache misses, memory loads and stores take | |
344 | ;; two cycles. Any special cases are handled in pa_adjust_cost. | |
345 | (define_function_unit "pa7200memory" 1 0 | |
346 | (and (eq_attr "type" "load,fpload,store,fpstore") | |
347 | (eq_attr "cpu" "7200")) 2 0) | |
348 | ||
349 | ;; I don't have detailed information on the PA7200 FP pipeline, so I | |
350 | ;; treat it just like the 7100LC pipeline. | |
351 | ;; Similarly for the multi-issue fake units. | |
c47decad | 352 | |
c733e074 TM |
353 | \f |
354 | ;; Compare instructions. | |
355 | ;; This controls RTL generation and register allocation. | |
356 | ||
876662ef | 357 | ;; We generate RTL for comparisons and branches by having the cmpxx |
c733e074 TM |
358 | ;; patterns store away the operands. Then, the scc and bcc patterns |
359 | ;; emit RTL for both the compare and the branch. | |
360 | ;; | |
361 | ||
362 | (define_expand "cmpsi" | |
363 | [(set (reg:CC 0) | |
364 | (compare:CC (match_operand:SI 0 "reg_or_0_operand" "") | |
365 | (match_operand:SI 1 "arith5_operand" "")))] | |
366 | "" | |
367 | " | |
368 | { | |
369 | hppa_compare_op0 = operands[0]; | |
370 | hppa_compare_op1 = operands[1]; | |
371 | hppa_branch_type = CMP_SI; | |
372 | DONE; | |
373 | }") | |
374 | ||
375 | (define_expand "cmpsf" | |
376 | [(set (reg:CCFP 0) | |
222727e8 JL |
377 | (compare:CCFP (match_operand:SF 0 "reg_or_0_operand" "") |
378 | (match_operand:SF 1 "reg_or_0_operand" "")))] | |
925cf581 | 379 | "! TARGET_SOFT_FLOAT" |
c733e074 TM |
380 | " |
381 | { | |
382 | hppa_compare_op0 = operands[0]; | |
383 | hppa_compare_op1 = operands[1]; | |
384 | hppa_branch_type = CMP_SF; | |
385 | DONE; | |
386 | }") | |
387 | ||
388 | (define_expand "cmpdf" | |
389 | [(set (reg:CCFP 0) | |
222727e8 JL |
390 | (compare:CCFP (match_operand:DF 0 "reg_or_0_operand" "") |
391 | (match_operand:DF 1 "reg_or_0_operand" "")))] | |
925cf581 | 392 | "! TARGET_SOFT_FLOAT" |
c733e074 TM |
393 | " |
394 | { | |
395 | hppa_compare_op0 = operands[0]; | |
396 | hppa_compare_op1 = operands[1]; | |
397 | hppa_branch_type = CMP_DF; | |
398 | DONE; | |
399 | }") | |
400 | ||
401 | (define_insn "" | |
2f95ebc2 TG |
402 | [(set (reg:CCFP 0) |
403 | (match_operator:CCFP 2 "comparison_operator" | |
0b27d5dd TG |
404 | [(match_operand:SF 0 "reg_or_0_operand" "fG") |
405 | (match_operand:SF 1 "reg_or_0_operand" "fG")]))] | |
925cf581 | 406 | "! TARGET_SOFT_FLOAT" |
d8b79470 | 407 | "fcmp,sgl,%Y2 %r0,%r1" |
c47decad JL |
408 | [(set_attr "length" "4") |
409 | (set_attr "type" "fpcc")]) | |
c733e074 TM |
410 | |
411 | (define_insn "" | |
2f95ebc2 TG |
412 | [(set (reg:CCFP 0) |
413 | (match_operator:CCFP 2 "comparison_operator" | |
0b27d5dd TG |
414 | [(match_operand:DF 0 "reg_or_0_operand" "fG") |
415 | (match_operand:DF 1 "reg_or_0_operand" "fG")]))] | |
925cf581 | 416 | "! TARGET_SOFT_FLOAT" |
d8b79470 | 417 | "fcmp,dbl,%Y2 %r0,%r1" |
c47decad JL |
418 | [(set_attr "length" "4") |
419 | (set_attr "type" "fpcc")]) | |
c733e074 TM |
420 | |
421 | ;; scc insns. | |
422 | ||
c733e074 TM |
423 | (define_expand "seq" |
424 | [(set (match_operand:SI 0 "register_operand" "") | |
d2a94ec0 | 425 | (eq:SI (match_dup 1) |
c733e074 TM |
426 | (match_dup 2)))] |
427 | "" | |
428 | " | |
429 | { | |
23c6329e | 430 | /* fp scc patterns rarely match, and are not a win on the PA. */ |
c733e074 | 431 | if (hppa_branch_type != CMP_SI) |
23c6329e | 432 | FAIL; |
c733e074 TM |
433 | /* set up operands from compare. */ |
434 | operands[1] = hppa_compare_op0; | |
435 | operands[2] = hppa_compare_op1; | |
436 | /* fall through and generate default code */ | |
437 | }") | |
438 | ||
439 | (define_expand "sne" | |
876662ef | 440 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 441 | (ne:SI (match_dup 1) |
c733e074 TM |
442 | (match_dup 2)))] |
443 | "" | |
444 | " | |
445 | { | |
23c6329e | 446 | /* fp scc patterns rarely match, and are not a win on the PA. */ |
c733e074 | 447 | if (hppa_branch_type != CMP_SI) |
23c6329e | 448 | FAIL; |
c733e074 TM |
449 | operands[1] = hppa_compare_op0; |
450 | operands[2] = hppa_compare_op1; | |
451 | }") | |
452 | ||
453 | (define_expand "slt" | |
876662ef | 454 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 455 | (lt:SI (match_dup 1) |
c733e074 TM |
456 | (match_dup 2)))] |
457 | "" | |
458 | " | |
459 | { | |
23c6329e | 460 | /* fp scc patterns rarely match, and are not a win on the PA. */ |
c733e074 | 461 | if (hppa_branch_type != CMP_SI) |
23c6329e | 462 | FAIL; |
c733e074 TM |
463 | operands[1] = hppa_compare_op0; |
464 | operands[2] = hppa_compare_op1; | |
465 | }") | |
466 | ||
467 | (define_expand "sgt" | |
876662ef | 468 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 469 | (gt:SI (match_dup 1) |
c733e074 TM |
470 | (match_dup 2)))] |
471 | "" | |
472 | " | |
473 | { | |
23c6329e | 474 | /* fp scc patterns rarely match, and are not a win on the PA. */ |
c733e074 | 475 | if (hppa_branch_type != CMP_SI) |
23c6329e | 476 | FAIL; |
c733e074 TM |
477 | operands[1] = hppa_compare_op0; |
478 | operands[2] = hppa_compare_op1; | |
479 | }") | |
480 | ||
481 | (define_expand "sle" | |
876662ef | 482 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 483 | (le:SI (match_dup 1) |
c733e074 TM |
484 | (match_dup 2)))] |
485 | "" | |
486 | " | |
487 | { | |
23c6329e | 488 | /* fp scc patterns rarely match, and are not a win on the PA. */ |
c733e074 | 489 | if (hppa_branch_type != CMP_SI) |
23c6329e | 490 | FAIL; |
c733e074 TM |
491 | operands[1] = hppa_compare_op0; |
492 | operands[2] = hppa_compare_op1; | |
493 | }") | |
494 | ||
495 | (define_expand "sge" | |
876662ef | 496 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 497 | (ge:SI (match_dup 1) |
c733e074 TM |
498 | (match_dup 2)))] |
499 | "" | |
500 | " | |
501 | { | |
23c6329e | 502 | /* fp scc patterns rarely match, and are not a win on the PA. */ |
c733e074 | 503 | if (hppa_branch_type != CMP_SI) |
23c6329e | 504 | FAIL; |
c733e074 TM |
505 | operands[1] = hppa_compare_op0; |
506 | operands[2] = hppa_compare_op1; | |
507 | }") | |
508 | ||
509 | (define_expand "sltu" | |
876662ef | 510 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 511 | (ltu:SI (match_dup 1) |
c733e074 TM |
512 | (match_dup 2)))] |
513 | "" | |
514 | " | |
515 | { | |
516 | if (hppa_branch_type != CMP_SI) | |
517 | FAIL; | |
518 | operands[1] = hppa_compare_op0; | |
519 | operands[2] = hppa_compare_op1; | |
520 | }") | |
521 | ||
522 | (define_expand "sgtu" | |
876662ef | 523 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 524 | (gtu:SI (match_dup 1) |
c733e074 TM |
525 | (match_dup 2)))] |
526 | "" | |
527 | " | |
528 | { | |
529 | if (hppa_branch_type != CMP_SI) | |
530 | FAIL; | |
531 | operands[1] = hppa_compare_op0; | |
532 | operands[2] = hppa_compare_op1; | |
533 | }") | |
534 | ||
535 | (define_expand "sleu" | |
876662ef | 536 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 537 | (leu:SI (match_dup 1) |
c733e074 TM |
538 | (match_dup 2)))] |
539 | "" | |
540 | " | |
541 | { | |
542 | if (hppa_branch_type != CMP_SI) | |
543 | FAIL; | |
544 | operands[1] = hppa_compare_op0; | |
545 | operands[2] = hppa_compare_op1; | |
546 | }") | |
547 | ||
548 | (define_expand "sgeu" | |
876662ef | 549 | [(set (match_operand:SI 0 "register_operand" "") |
d2a94ec0 | 550 | (geu:SI (match_dup 1) |
c733e074 TM |
551 | (match_dup 2)))] |
552 | "" | |
553 | " | |
554 | { | |
555 | if (hppa_branch_type != CMP_SI) | |
556 | FAIL; | |
557 | operands[1] = hppa_compare_op0; | |
558 | operands[2] = hppa_compare_op1; | |
559 | }") | |
560 | ||
561 | ;; Instruction canonicalization puts immediate operands second, which | |
562 | ;; is the reverse of what we want. | |
563 | ||
fd0214cd | 564 | (define_insn "scc" |
6f672dc0 | 565 | [(set (match_operand:SI 0 "register_operand" "=r") |
d2a94ec0 | 566 | (match_operator:SI 3 "comparison_operator" |
6f672dc0 | 567 | [(match_operand:SI 1 "register_operand" "r") |
2f95ebc2 | 568 | (match_operand:SI 2 "arith11_operand" "rI")]))] |
c733e074 | 569 | "" |
6f672dc0 TG |
570 | "com%I2clr,%B3 %2,%1,%0\;ldi 1,%0" |
571 | [(set_attr "type" "binary") | |
4c2164b7 | 572 | (set_attr "length" "8")]) |
c733e074 | 573 | |
2f95ebc2 TG |
574 | (define_insn "iorscc" |
575 | [(set (match_operand:SI 0 "register_operand" "=r") | |
576 | (ior:SI (match_operator:SI 3 "comparison_operator" | |
577 | [(match_operand:SI 1 "register_operand" "r") | |
578 | (match_operand:SI 2 "arith11_operand" "rI")]) | |
579 | (match_operator:SI 6 "comparison_operator" | |
580 | [(match_operand:SI 4 "register_operand" "r") | |
581 | (match_operand:SI 5 "arith11_operand" "rI")])))] | |
582 | "" | |
ac7198ef | 583 | "com%I2clr,%S3 %2,%1,0\;com%I5clr,%B6 %5,%4,%0\;ldi 1,%0" |
2f95ebc2 | 584 | [(set_attr "type" "binary") |
c47decad | 585 | (set_attr "length" "12")]) |
2f95ebc2 | 586 | |
fd0214cd | 587 | ;; Combiner patterns for common operations performed with the output |
2f95ebc2 | 588 | ;; from an scc insn (negscc and incscc). |
fd0214cd | 589 | (define_insn "negscc" |
6f672dc0 | 590 | [(set (match_operand:SI 0 "register_operand" "=r") |
2878315f | 591 | (neg:SI (match_operator:SI 3 "comparison_operator" |
6f672dc0 | 592 | [(match_operand:SI 1 "register_operand" "r") |
2f95ebc2 | 593 | (match_operand:SI 2 "arith11_operand" "rI")])))] |
fd0214cd | 594 | "" |
6f672dc0 TG |
595 | "com%I2clr,%B3 %2,%1,%0\;ldi -1,%0" |
596 | [(set_attr "type" "binary") | |
4c2164b7 | 597 | (set_attr "length" "8")]) |
6f672dc0 TG |
598 | |
599 | ;; Patterns for adding/subtracting the result of a boolean expression from | |
600 | ;; a register. First we have special patterns that make use of the carry | |
601 | ;; bit, and output only two instructions. For the cases we can't in | |
602 | ;; general do in two instructions, the incscc pattern at the end outputs | |
603 | ;; two or three instructions. | |
604 | ||
605 | (define_insn "" | |
606 | [(set (match_operand:SI 0 "register_operand" "=r") | |
607 | (plus:SI (leu:SI (match_operand:SI 2 "register_operand" "r") | |
608 | (match_operand:SI 3 "arith11_operand" "rI")) | |
609 | (match_operand:SI 1 "register_operand" "r")))] | |
610 | "" | |
611 | "sub%I3 %3,%2,0\;addc 0,%1,%0" | |
612 | [(set_attr "type" "binary") | |
4c2164b7 | 613 | (set_attr "length" "8")]) |
6f672dc0 TG |
614 | |
615 | ; This need only accept registers for op3, since canonicalization | |
616 | ; replaces geu with gtu when op3 is an integer. | |
617 | (define_insn "" | |
618 | [(set (match_operand:SI 0 "register_operand" "=r") | |
619 | (plus:SI (geu:SI (match_operand:SI 2 "register_operand" "r") | |
620 | (match_operand:SI 3 "register_operand" "r")) | |
621 | (match_operand:SI 1 "register_operand" "r")))] | |
622 | "" | |
623 | "sub %2,%3,0\;addc 0,%1,%0" | |
624 | [(set_attr "type" "binary") | |
4c2164b7 | 625 | (set_attr "length" "8")]) |
6f672dc0 TG |
626 | |
627 | ; Match only integers for op3 here. This is used as canonical form of the | |
628 | ; geu pattern when op3 is an integer. Don't match registers since we can't | |
629 | ; make better code than the general incscc pattern. | |
630 | (define_insn "" | |
631 | [(set (match_operand:SI 0 "register_operand" "=r") | |
632 | (plus:SI (gtu:SI (match_operand:SI 2 "register_operand" "r") | |
633 | (match_operand:SI 3 "int11_operand" "I")) | |
634 | (match_operand:SI 1 "register_operand" "r")))] | |
635 | "" | |
636 | "addi %k3,%2,0\;addc 0,%1,%0" | |
fd0214cd | 637 | [(set_attr "type" "binary") |
4c2164b7 | 638 | (set_attr "length" "8")]) |
fd0214cd | 639 | |
fd0214cd JL |
640 | (define_insn "incscc" |
641 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
6f672dc0 TG |
642 | (plus:SI (match_operator:SI 4 "comparison_operator" |
643 | [(match_operand:SI 2 "register_operand" "r,r") | |
644 | (match_operand:SI 3 "arith11_operand" "rI,rI")]) | |
645 | (match_operand:SI 1 "register_operand" "0,?r")))] | |
646 | "" | |
647 | "@ | |
648 | com%I3clr,%B4 %3,%2,0\;addi 1,%0,%0 | |
649 | com%I3clr,%B4 %3,%2,0\;addi,tr 1,%1,%0\;copy %1,%0" | |
650 | [(set_attr "type" "binary,binary") | |
4c2164b7 | 651 | (set_attr "length" "8,12")]) |
6f672dc0 TG |
652 | |
653 | (define_insn "" | |
654 | [(set (match_operand:SI 0 "register_operand" "=r") | |
655 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
656 | (gtu:SI (match_operand:SI 2 "register_operand" "r") | |
657 | (match_operand:SI 3 "arith11_operand" "rI"))))] | |
658 | "" | |
659 | "sub%I3 %3,%2,0\;subb %1,0,%0" | |
660 | [(set_attr "type" "binary") | |
4c2164b7 | 661 | (set_attr "length" "8")]) |
6f672dc0 | 662 | |
2f95ebc2 TG |
663 | (define_insn "" |
664 | [(set (match_operand:SI 0 "register_operand" "=r") | |
665 | (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") | |
666 | (gtu:SI (match_operand:SI 2 "register_operand" "r") | |
667 | (match_operand:SI 3 "arith11_operand" "rI"))) | |
668 | (match_operand:SI 4 "register_operand" "r")))] | |
669 | "" | |
670 | "sub%I3 %3,%2,0\;subb %1,%4,%0" | |
671 | [(set_attr "type" "binary") | |
672 | (set_attr "length" "8")]) | |
673 | ||
6f672dc0 TG |
674 | ; This need only accept registers for op3, since canonicalization |
675 | ; replaces ltu with leu when op3 is an integer. | |
676 | (define_insn "" | |
677 | [(set (match_operand:SI 0 "register_operand" "=r") | |
678 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
679 | (ltu:SI (match_operand:SI 2 "register_operand" "r") | |
680 | (match_operand:SI 3 "register_operand" "r"))))] | |
681 | "" | |
682 | "sub %2,%3,0\;subb %1,0,%0" | |
683 | [(set_attr "type" "binary") | |
4c2164b7 | 684 | (set_attr "length" "8")]) |
6f672dc0 | 685 | |
2f95ebc2 TG |
686 | (define_insn "" |
687 | [(set (match_operand:SI 0 "register_operand" "=r") | |
688 | (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") | |
689 | (ltu:SI (match_operand:SI 2 "register_operand" "r") | |
690 | (match_operand:SI 3 "register_operand" "r"))) | |
691 | (match_operand:SI 4 "register_operand" "r")))] | |
692 | "" | |
693 | "sub %2,%3,0\;subb %1,%4,%0" | |
694 | [(set_attr "type" "binary") | |
695 | (set_attr "length" "8")]) | |
696 | ||
6f672dc0 TG |
697 | ; Match only integers for op3 here. This is used as canonical form of the |
698 | ; ltu pattern when op3 is an integer. Don't match registers since we can't | |
699 | ; make better code than the general incscc pattern. | |
700 | (define_insn "" | |
701 | [(set (match_operand:SI 0 "register_operand" "=r") | |
702 | (minus:SI (match_operand:SI 1 "register_operand" "r") | |
703 | (leu:SI (match_operand:SI 2 "register_operand" "r") | |
704 | (match_operand:SI 3 "int11_operand" "I"))))] | |
705 | "" | |
706 | "addi %k3,%2,0\;subb %1,0,%0" | |
707 | [(set_attr "type" "binary") | |
4c2164b7 | 708 | (set_attr "length" "8")]) |
6f672dc0 | 709 | |
2f95ebc2 TG |
710 | (define_insn "" |
711 | [(set (match_operand:SI 0 "register_operand" "=r") | |
712 | (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") | |
713 | (leu:SI (match_operand:SI 2 "register_operand" "r") | |
714 | (match_operand:SI 3 "int11_operand" "I"))) | |
715 | (match_operand:SI 4 "register_operand" "r")))] | |
716 | "" | |
717 | "addi %k3,%2,0\;subb %1,%4,%0" | |
718 | [(set_attr "type" "binary") | |
719 | (set_attr "length" "8")]) | |
720 | ||
6f672dc0 TG |
721 | (define_insn "decscc" |
722 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
723 | (minus:SI (match_operand:SI 1 "register_operand" "0,?r") | |
724 | (match_operator:SI 4 "comparison_operator" | |
725 | [(match_operand:SI 2 "register_operand" "r,r") | |
726 | (match_operand:SI 3 "arith11_operand" "rI,rI")])))] | |
727 | "" | |
728 | "@ | |
729 | com%I3clr,%B4 %3,%2,0\;addi -1,%0,%0 | |
730 | com%I3clr,%B4 %3,%2,0\;addi,tr -1,%1,%0\;copy %1,%0" | |
fd0214cd | 731 | [(set_attr "type" "binary,binary") |
4c2164b7 | 732 | (set_attr "length" "8,12")]) |
ac153498 | 733 | |
751a3523 JL |
734 | ; Patterns for max and min. (There is no need for an earlyclobber in the |
735 | ; last alternative since the middle alternative will match if op0 == op1.) | |
736 | ||
99457156 JL |
737 | (define_insn "sminsi3" |
738 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
751a3523 JL |
739 | (smin:SI (match_operand:SI 1 "register_operand" "%0,0,r") |
740 | (match_operand:SI 2 "arith11_operand" "r,I,M")))] | |
99457156 JL |
741 | "" |
742 | "@ | |
99457156 | 743 | comclr,> %2,%0,0\;copy %2,%0 |
751a3523 JL |
744 | comiclr,> %2,%0,0\;ldi %2,%0 |
745 | comclr,> %1,%2,%0\;copy %1,%0" | |
99457156 | 746 | [(set_attr "type" "multi,multi,multi") |
4c2164b7 | 747 | (set_attr "length" "8,8,8")]) |
99457156 JL |
748 | |
749 | (define_insn "uminsi3" | |
750 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
751 | (umin:SI (match_operand:SI 1 "register_operand" "%0,0") | |
752 | (match_operand:SI 2 "arith11_operand" "r,I")))] | |
753 | "" | |
754 | "@ | |
755 | comclr,>> %2,%0,0\;copy %2,%0 | |
756 | comiclr,>> %2,%0,0\;ldi %2,%0" | |
757 | [(set_attr "type" "multi,multi") | |
4c2164b7 | 758 | (set_attr "length" "8,8")]) |
99457156 JL |
759 | |
760 | (define_insn "smaxsi3" | |
761 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
751a3523 JL |
762 | (smax:SI (match_operand:SI 1 "register_operand" "%0,0,r") |
763 | (match_operand:SI 2 "arith11_operand" "r,I,M")))] | |
99457156 JL |
764 | "" |
765 | "@ | |
99457156 | 766 | comclr,< %2,%0,0\;copy %2,%0 |
751a3523 JL |
767 | comiclr,< %2,%0,0\;ldi %2,%0 |
768 | comclr,< %1,%2,%0\;copy %1,%0" | |
99457156 | 769 | [(set_attr "type" "multi,multi,multi") |
4c2164b7 | 770 | (set_attr "length" "8,8,8")]) |
99457156 JL |
771 | |
772 | (define_insn "umaxsi3" | |
773 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
774 | (umax:SI (match_operand:SI 1 "register_operand" "%0,0") | |
775 | (match_operand:SI 2 "arith11_operand" "r,I")))] | |
776 | "" | |
777 | "@ | |
778 | comclr,<< %2,%0,0\;copy %2,%0 | |
779 | comiclr,<< %2,%0,0\;ldi %2,%0" | |
780 | [(set_attr "type" "multi,multi") | |
4c2164b7 | 781 | (set_attr "length" "8,8")]) |
68944452 JL |
782 | |
783 | (define_insn "abssi2" | |
784 | [(set (match_operand:SI 0 "register_operand" "=r") | |
77c87273 | 785 | (abs:SI (match_operand:SI 1 "register_operand" "r")))] |
68944452 | 786 | "" |
f2be3a72 | 787 | "or,>= %%r0,%1,%0\;subi 0,%0,%0" |
68944452 JL |
788 | [(set_attr "type" "multi") |
789 | (set_attr "length" "8")]) | |
790 | ||
78878730 | 791 | ;;; Experimental conditional move patterns |
ac153498 | 792 | |
014a4565 JL |
793 | (define_expand "movsicc" |
794 | [(set (match_operand:SI 0 "register_operand" "") | |
795 | (if_then_else:SI | |
796 | (match_operator 1 "comparison_operator" | |
549fd8ff RK |
797 | [(match_dup 4) |
798 | (match_dup 5)]) | |
014a4565 JL |
799 | (match_operand:SI 2 "reg_or_cint_move_operand" "") |
800 | (match_operand:SI 3 "reg_or_cint_move_operand" "")))] | |
801 | "" | |
802 | " | |
803 | { | |
804 | enum rtx_code code = GET_CODE (operands[1]); | |
805 | ||
806 | if (hppa_branch_type != CMP_SI) | |
807 | FAIL; | |
808 | ||
809 | /* operands[1] is currently the result of compare_from_rtx. We want to | |
810 | emit a compare of the original operands. */ | |
811 | operands[1] = gen_rtx (code, SImode, hppa_compare_op0, hppa_compare_op1); | |
812 | operands[4] = hppa_compare_op0; | |
813 | operands[5] = hppa_compare_op1; | |
814 | }") | |
815 | ||
78878730 TG |
816 | ; We need the first constraint alternative in order to avoid |
817 | ; earlyclobbers on all other alternatives. | |
818 | (define_insn "" | |
819 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") | |
820 | (if_then_else:SI | |
821 | (match_operator 5 "comparison_operator" | |
822 | [(match_operand:SI 3 "register_operand" "r,r,r,r,r") | |
823 | (match_operand:SI 4 "arith11_operand" "rI,rI,rI,rI,rI")]) | |
824 | (match_operand:SI 1 "reg_or_cint_move_operand" "0,r,J,N,K") | |
825 | (const_int 0)))] | |
826 | "" | |
827 | "@ | |
828 | com%I4clr,%S5 %4,%3,0\;ldi 0,%0 | |
829 | com%I4clr,%B5 %4,%3,%0\;copy %1,%0 | |
830 | com%I4clr,%B5 %4,%3,%0\;ldi %1,%0 | |
831 | com%I4clr,%B5 %4,%3,%0\;ldil L'%1,%0 | |
832 | com%I4clr,%B5 %4,%3,%0\;zdepi %Z1,%0" | |
c47decad | 833 | [(set_attr "type" "multi,multi,multi,multi,nullshift") |
4c2164b7 | 834 | (set_attr "length" "8,8,8,8,8")]) |
78878730 TG |
835 | |
836 | (define_insn "" | |
837 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r") | |
202571cd | 838 | (if_then_else:SI |
ac153498 | 839 | (match_operator 5 "comparison_operator" |
78878730 TG |
840 | [(match_operand:SI 3 "register_operand" "r,r,r,r,r,r,r,r") |
841 | (match_operand:SI 4 "arith11_operand" "rI,rI,rI,rI,rI,rI,rI,rI")]) | |
842 | (match_operand:SI 1 "reg_or_cint_move_operand" "0,0,0,0,r,J,N,K") | |
843 | (match_operand:SI 2 "reg_or_cint_move_operand" "r,J,N,K,0,0,0,0")))] | |
ac153498 | 844 | "" |
202571cd TG |
845 | "@ |
846 | com%I4clr,%S5 %4,%3,0\;copy %2,%0 | |
847 | com%I4clr,%S5 %4,%3,0\;ldi %2,%0 | |
78878730 TG |
848 | com%I4clr,%S5 %4,%3,0\;ldil L'%2,%0 |
849 | com%I4clr,%S5 %4,%3,0\;zdepi %Z2,%0 | |
850 | com%I4clr,%B5 %4,%3,0\;copy %1,%0 | |
851 | com%I4clr,%B5 %4,%3,0\;ldi %1,%0 | |
852 | com%I4clr,%B5 %4,%3,0\;ldil L'%1,%0 | |
853 | com%I4clr,%B5 %4,%3,0\;zdepi %Z1,%0" | |
c47decad | 854 | [(set_attr "type" "multi,multi,multi,nullshift,multi,multi,multi,nullshift") |
4c2164b7 | 855 | (set_attr "length" "8,8,8,8,8,8,8,8")]) |
ac153498 TG |
856 | |
857 | ;; Conditional Branches | |
c733e074 TM |
858 | |
859 | (define_expand "beq" | |
860 | [(set (pc) | |
861 | (if_then_else (eq (match_dup 1) (match_dup 2)) | |
862 | (label_ref (match_operand 0 "" "")) | |
863 | (pc)))] | |
864 | "" | |
865 | " | |
866 | { | |
867 | if (hppa_branch_type != CMP_SI) | |
868 | { | |
869 | emit_insn (gen_cmp_fp (EQ, hppa_compare_op0, hppa_compare_op1)); | |
870 | emit_bcond_fp (NE, operands[0]); | |
871 | DONE; | |
872 | } | |
873 | /* set up operands from compare. */ | |
874 | operands[1] = hppa_compare_op0; | |
875 | operands[2] = hppa_compare_op1; | |
876 | /* fall through and generate default code */ | |
877 | }") | |
878 | ||
879 | (define_expand "bne" | |
880 | [(set (pc) | |
881 | (if_then_else (ne (match_dup 1) (match_dup 2)) | |
882 | (label_ref (match_operand 0 "" "")) | |
883 | (pc)))] | |
884 | "" | |
885 | " | |
886 | { | |
887 | if (hppa_branch_type != CMP_SI) | |
888 | { | |
889 | emit_insn (gen_cmp_fp (NE, hppa_compare_op0, hppa_compare_op1)); | |
890 | emit_bcond_fp (NE, operands[0]); | |
891 | DONE; | |
892 | } | |
893 | operands[1] = hppa_compare_op0; | |
894 | operands[2] = hppa_compare_op1; | |
895 | }") | |
896 | ||
897 | (define_expand "bgt" | |
898 | [(set (pc) | |
899 | (if_then_else (gt (match_dup 1) (match_dup 2)) | |
900 | (label_ref (match_operand 0 "" "")) | |
901 | (pc)))] | |
902 | "" | |
903 | " | |
904 | { | |
905 | if (hppa_branch_type != CMP_SI) | |
906 | { | |
907 | emit_insn (gen_cmp_fp (GT, hppa_compare_op0, hppa_compare_op1)); | |
908 | emit_bcond_fp (NE, operands[0]); | |
909 | DONE; | |
910 | } | |
911 | operands[1] = hppa_compare_op0; | |
912 | operands[2] = hppa_compare_op1; | |
913 | }") | |
914 | ||
915 | (define_expand "blt" | |
916 | [(set (pc) | |
917 | (if_then_else (lt (match_dup 1) (match_dup 2)) | |
918 | (label_ref (match_operand 0 "" "")) | |
919 | (pc)))] | |
920 | "" | |
921 | " | |
922 | { | |
923 | if (hppa_branch_type != CMP_SI) | |
924 | { | |
925 | emit_insn (gen_cmp_fp (LT, hppa_compare_op0, hppa_compare_op1)); | |
926 | emit_bcond_fp (NE, operands[0]); | |
927 | DONE; | |
928 | } | |
929 | operands[1] = hppa_compare_op0; | |
930 | operands[2] = hppa_compare_op1; | |
931 | }") | |
932 | ||
933 | (define_expand "bge" | |
934 | [(set (pc) | |
935 | (if_then_else (ge (match_dup 1) (match_dup 2)) | |
936 | (label_ref (match_operand 0 "" "")) | |
937 | (pc)))] | |
938 | "" | |
939 | " | |
940 | { | |
941 | if (hppa_branch_type != CMP_SI) | |
942 | { | |
943 | emit_insn (gen_cmp_fp (GE, hppa_compare_op0, hppa_compare_op1)); | |
944 | emit_bcond_fp (NE, operands[0]); | |
945 | DONE; | |
946 | } | |
947 | operands[1] = hppa_compare_op0; | |
948 | operands[2] = hppa_compare_op1; | |
949 | }") | |
950 | ||
951 | (define_expand "ble" | |
952 | [(set (pc) | |
953 | (if_then_else (le (match_dup 1) (match_dup 2)) | |
954 | (label_ref (match_operand 0 "" "")) | |
955 | (pc)))] | |
956 | "" | |
957 | " | |
958 | { | |
959 | if (hppa_branch_type != CMP_SI) | |
960 | { | |
961 | emit_insn (gen_cmp_fp (LE, hppa_compare_op0, hppa_compare_op1)); | |
962 | emit_bcond_fp (NE, operands[0]); | |
963 | DONE; | |
964 | } | |
965 | operands[1] = hppa_compare_op0; | |
966 | operands[2] = hppa_compare_op1; | |
967 | }") | |
968 | ||
969 | (define_expand "bgtu" | |
970 | [(set (pc) | |
971 | (if_then_else (gtu (match_dup 1) (match_dup 2)) | |
972 | (label_ref (match_operand 0 "" "")) | |
973 | (pc)))] | |
974 | "" | |
975 | " | |
976 | { | |
977 | if (hppa_branch_type != CMP_SI) | |
978 | FAIL; | |
979 | operands[1] = hppa_compare_op0; | |
980 | operands[2] = hppa_compare_op1; | |
981 | }") | |
982 | ||
983 | (define_expand "bltu" | |
984 | [(set (pc) | |
985 | (if_then_else (ltu (match_dup 1) (match_dup 2)) | |
986 | (label_ref (match_operand 0 "" "")) | |
987 | (pc)))] | |
988 | "" | |
989 | " | |
990 | { | |
991 | if (hppa_branch_type != CMP_SI) | |
992 | FAIL; | |
993 | operands[1] = hppa_compare_op0; | |
994 | operands[2] = hppa_compare_op1; | |
995 | }") | |
996 | ||
997 | (define_expand "bgeu" | |
998 | [(set (pc) | |
999 | (if_then_else (geu (match_dup 1) (match_dup 2)) | |
1000 | (label_ref (match_operand 0 "" "")) | |
1001 | (pc)))] | |
1002 | "" | |
1003 | " | |
1004 | { | |
1005 | if (hppa_branch_type != CMP_SI) | |
1006 | FAIL; | |
1007 | operands[1] = hppa_compare_op0; | |
1008 | operands[2] = hppa_compare_op1; | |
1009 | }") | |
1010 | ||
1011 | (define_expand "bleu" | |
1012 | [(set (pc) | |
1013 | (if_then_else (leu (match_dup 1) (match_dup 2)) | |
1014 | (label_ref (match_operand 0 "" "")) | |
1015 | (pc)))] | |
1016 | "" | |
1017 | " | |
1018 | { | |
1019 | if (hppa_branch_type != CMP_SI) | |
1020 | FAIL; | |
1021 | operands[1] = hppa_compare_op0; | |
1022 | operands[2] = hppa_compare_op1; | |
1023 | }") | |
1024 | ||
1025 | ;; Match the branch patterns. | |
1026 | ||
99457156 JL |
1027 | |
1028 | ;; Note a long backward conditional branch with an annulled delay slot | |
2f95ebc2 | 1029 | ;; has a length of 12. |
c733e074 TM |
1030 | (define_insn "" |
1031 | [(set (pc) | |
1032 | (if_then_else | |
1033 | (match_operator 3 "comparison_operator" | |
2bc0b543 JL |
1034 | [(match_operand:SI 1 "register_operand" "r") |
1035 | (match_operand:SI 2 "arith5_operand" "rL")]) | |
c733e074 TM |
1036 | (label_ref (match_operand 0 "" "")) |
1037 | (pc)))] | |
1038 | "" | |
1039 | "* | |
1040 | { | |
2f95ebc2 | 1041 | return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), |
99457156 | 1042 | get_attr_length (insn), 0, insn); |
c733e074 | 1043 | }" |
99457156 | 1044 | [(set_attr "type" "cbranch") |
2f95ebc2 | 1045 | (set (attr "length") |
4bcb9e3f JL |
1046 | (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) |
1047 | (const_int 8184)) | |
1048 | (const_int 4) | |
1049 | (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) | |
1050 | (const_int 262100)) | |
1051 | (const_int 8) | |
1052 | (eq (symbol_ref "flag_pic") (const_int 0)) | |
1053 | (const_int 20)] | |
1054 | (const_int 28)))]) | |
c733e074 TM |
1055 | |
1056 | ;; Match the negated branch. | |
1057 | ||
1058 | (define_insn "" | |
1059 | [(set (pc) | |
1060 | (if_then_else | |
1061 | (match_operator 3 "comparison_operator" | |
2bc0b543 JL |
1062 | [(match_operand:SI 1 "register_operand" "r") |
1063 | (match_operand:SI 2 "arith5_operand" "rL")]) | |
c733e074 TM |
1064 | (pc) |
1065 | (label_ref (match_operand 0 "" ""))))] | |
1066 | "" | |
1067 | "* | |
1068 | { | |
2f95ebc2 | 1069 | return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), |
99457156 | 1070 | get_attr_length (insn), 1, insn); |
c733e074 | 1071 | }" |
99457156 | 1072 | [(set_attr "type" "cbranch") |
2f95ebc2 | 1073 | (set (attr "length") |
4bcb9e3f JL |
1074 | (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) |
1075 | (const_int 8184)) | |
1076 | (const_int 4) | |
1077 | (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) | |
1078 | (const_int 262100)) | |
1079 | (const_int 8) | |
1080 | (eq (symbol_ref "flag_pic") (const_int 0)) | |
1081 | (const_int 20)] | |
1082 | (const_int 28)))]) | |
99457156 JL |
1083 | |
1084 | ;; Branch on Bit patterns. | |
e19ee659 TG |
1085 | (define_insn "" |
1086 | [(set (pc) | |
1087 | (if_then_else | |
1088 | (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
1089 | (const_int 1) | |
1090 | (match_operand:SI 1 "uint5_operand" "")) | |
1091 | (const_int 0)) | |
ff0a4409 JL |
1092 | (label_ref (match_operand 2 "" "")) |
1093 | (pc)))] | |
e19ee659 TG |
1094 | "" |
1095 | "* | |
1096 | { | |
2f95ebc2 | 1097 | return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), |
ff0a4409 | 1098 | get_attr_length (insn), 0, insn, 0); |
e19ee659 | 1099 | }" |
99457156 | 1100 | [(set_attr "type" "cbranch") |
2f95ebc2 | 1101 | (set (attr "length") |
ff0a4409 | 1102 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) |
6a73009d | 1103 | (const_int 8184)) |
ff0a4409 JL |
1104 | (const_int 4) |
1105 | (const_int 8)))]) | |
1106 | ||
1107 | (define_insn "" | |
1108 | [(set (pc) | |
1109 | (if_then_else | |
1110 | (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
1111 | (const_int 1) | |
1112 | (match_operand:SI 1 "uint5_operand" "")) | |
1113 | (const_int 0)) | |
1114 | (pc) | |
1115 | (label_ref (match_operand 2 "" ""))))] | |
1116 | "" | |
1117 | "* | |
1118 | { | |
1119 | return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), | |
1120 | get_attr_length (insn), 1, insn, 0); | |
1121 | }" | |
1122 | [(set_attr "type" "cbranch") | |
1123 | (set (attr "length") | |
1124 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
6a73009d | 1125 | (const_int 8184)) |
4c2164b7 JL |
1126 | (const_int 4) |
1127 | (const_int 8)))]) | |
e19ee659 TG |
1128 | |
1129 | (define_insn "" | |
1130 | [(set (pc) | |
1131 | (if_then_else | |
1132 | (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
1133 | (const_int 1) | |
1134 | (match_operand:SI 1 "uint5_operand" "")) | |
1135 | (const_int 0)) | |
ff0a4409 JL |
1136 | (label_ref (match_operand 2 "" "")) |
1137 | (pc)))] | |
e19ee659 TG |
1138 | "" |
1139 | "* | |
1140 | { | |
2f95ebc2 | 1141 | return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), |
ff0a4409 | 1142 | get_attr_length (insn), 0, insn, 1); |
e19ee659 | 1143 | }" |
99457156 | 1144 | [(set_attr "type" "cbranch") |
2f95ebc2 | 1145 | (set (attr "length") |
ff0a4409 | 1146 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) |
6a73009d | 1147 | (const_int 8184)) |
ff0a4409 JL |
1148 | (const_int 4) |
1149 | (const_int 8)))]) | |
1150 | ||
1151 | (define_insn "" | |
1152 | [(set (pc) | |
1153 | (if_then_else | |
1154 | (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
1155 | (const_int 1) | |
1156 | (match_operand:SI 1 "uint5_operand" "")) | |
1157 | (const_int 0)) | |
1158 | (pc) | |
1159 | (label_ref (match_operand 2 "" ""))))] | |
1160 | "" | |
1161 | "* | |
1162 | { | |
1163 | return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), | |
1164 | get_attr_length (insn), 1, insn, 1); | |
1165 | }" | |
1166 | [(set_attr "type" "cbranch") | |
1167 | (set (attr "length") | |
1168 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
6a73009d JL |
1169 | (const_int 8184)) |
1170 | (const_int 4) | |
1171 | (const_int 8)))]) | |
1172 | ||
1173 | ;; Branch on Variable Bit patterns. | |
1174 | (define_insn "" | |
1175 | [(set (pc) | |
1176 | (if_then_else | |
1177 | (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
1178 | (const_int 1) | |
1179 | (match_operand:SI 1 "register_operand" "q")) | |
1180 | (const_int 0)) | |
1181 | (label_ref (match_operand 2 "" "")) | |
1182 | (pc)))] | |
1183 | "" | |
1184 | "* | |
1185 | { | |
1186 | return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn), | |
1187 | get_attr_length (insn), 0, insn, 0); | |
1188 | }" | |
1189 | [(set_attr "type" "cbranch") | |
1190 | (set (attr "length") | |
1191 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
1192 | (const_int 8184)) | |
1193 | (const_int 4) | |
1194 | (const_int 8)))]) | |
1195 | ||
1196 | (define_insn "" | |
1197 | [(set (pc) | |
1198 | (if_then_else | |
1199 | (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
1200 | (const_int 1) | |
1201 | (match_operand:SI 1 "register_operand" "q")) | |
1202 | (const_int 0)) | |
1203 | (pc) | |
1204 | (label_ref (match_operand 2 "" ""))))] | |
1205 | "" | |
1206 | "* | |
1207 | { | |
1208 | return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn), | |
1209 | get_attr_length (insn), 1, insn, 0); | |
1210 | }" | |
1211 | [(set_attr "type" "cbranch") | |
1212 | (set (attr "length") | |
1213 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
1214 | (const_int 8184)) | |
1215 | (const_int 4) | |
1216 | (const_int 8)))]) | |
1217 | ||
1218 | (define_insn "" | |
1219 | [(set (pc) | |
1220 | (if_then_else | |
1221 | (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
1222 | (const_int 1) | |
1223 | (match_operand:SI 1 "register_operand" "q")) | |
1224 | (const_int 0)) | |
1225 | (label_ref (match_operand 2 "" "")) | |
1226 | (pc)))] | |
1227 | "" | |
1228 | "* | |
1229 | { | |
1230 | return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn), | |
1231 | get_attr_length (insn), 0, insn, 1); | |
1232 | }" | |
1233 | [(set_attr "type" "cbranch") | |
1234 | (set (attr "length") | |
1235 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
1236 | (const_int 8184)) | |
1237 | (const_int 4) | |
1238 | (const_int 8)))]) | |
1239 | ||
1240 | (define_insn "" | |
1241 | [(set (pc) | |
1242 | (if_then_else | |
1243 | (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
1244 | (const_int 1) | |
1245 | (match_operand:SI 1 "register_operand" "q")) | |
1246 | (const_int 0)) | |
1247 | (pc) | |
1248 | (label_ref (match_operand 2 "" ""))))] | |
1249 | "" | |
1250 | "* | |
1251 | { | |
1252 | return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn), | |
1253 | get_attr_length (insn), 1, insn, 1); | |
1254 | }" | |
1255 | [(set_attr "type" "cbranch") | |
1256 | (set (attr "length") | |
1257 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
1258 | (const_int 8184)) | |
4c2164b7 JL |
1259 | (const_int 4) |
1260 | (const_int 8)))]) | |
99457156 | 1261 | |
c733e074 | 1262 | ;; Floating point branches |
c733e074 TM |
1263 | (define_insn "" |
1264 | [(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0)) | |
1265 | (label_ref (match_operand 0 "" "")) | |
1266 | (pc)))] | |
925cf581 | 1267 | "! TARGET_SOFT_FLOAT" |
e9cfad81 JL |
1268 | "* |
1269 | { | |
1270 | if (INSN_ANNULLED_BRANCH_P (insn)) | |
1271 | return \"ftest\;bl,n %0,0\"; | |
1272 | else | |
1273 | return \"ftest\;bl%* %0,0\"; | |
1274 | }" | |
1275 | [(set_attr "type" "fbranch") | |
4c2164b7 | 1276 | (set_attr "length" "8")]) |
c733e074 TM |
1277 | |
1278 | (define_insn "" | |
1279 | [(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0)) | |
1280 | (pc) | |
1281 | (label_ref (match_operand 0 "" ""))))] | |
925cf581 | 1282 | "! TARGET_SOFT_FLOAT" |
e9cfad81 JL |
1283 | "* |
1284 | { | |
1285 | if (INSN_ANNULLED_BRANCH_P (insn)) | |
1286 | return \"ftest\;add,tr 0,0,0\;bl,n %0,0\"; | |
1287 | else | |
1288 | return \"ftest\;add,tr 0,0,0\;bl%* %0,0\"; | |
1289 | }" | |
1290 | [(set_attr "type" "fbranch") | |
4c2164b7 | 1291 | (set_attr "length" "12")]) |
c733e074 TM |
1292 | |
1293 | ;; Move instructions | |
1294 | ||
1295 | (define_expand "movsi" | |
1296 | [(set (match_operand:SI 0 "general_operand" "") | |
1297 | (match_operand:SI 1 "general_operand" ""))] | |
1298 | "" | |
1299 | " | |
1300 | { | |
d2a94ec0 | 1301 | if (emit_move_sequence (operands, SImode, 0)) |
c733e074 TM |
1302 | DONE; |
1303 | }") | |
1304 | ||
0fc4f911 RK |
1305 | ;; Reloading an SImode or DImode value requires a scratch register if |
1306 | ;; going in to or out of float point registers. | |
1307 | ||
1308 | (define_expand "reload_insi" | |
1309 | [(set (match_operand:SI 0 "register_operand" "=Z") | |
1310 | (match_operand:SI 1 "non_hard_reg_operand" "")) | |
1311 | (clobber (match_operand:SI 2 "register_operand" "=&r"))] | |
1312 | "" | |
1313 | " | |
1314 | { | |
1315 | if (emit_move_sequence (operands, SImode, operands[2])) | |
1316 | DONE; | |
1317 | ||
1318 | /* We don't want the clobber emitted, so handle this ourselves. */ | |
1319 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); | |
1320 | DONE; | |
1321 | }") | |
1322 | ||
1323 | (define_expand "reload_outsi" | |
1324 | [(set (match_operand:SI 0 "non_hard_reg_operand" "") | |
1325 | (match_operand:SI 1 "register_operand" "Z")) | |
1326 | (clobber (match_operand:SI 2 "register_operand" "=&r"))] | |
1327 | "" | |
1328 | " | |
1329 | { | |
1330 | if (emit_move_sequence (operands, SImode, operands[2])) | |
1331 | DONE; | |
1332 | ||
1333 | /* We don't want the clobber emitted, so handle this ourselves. */ | |
1334 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); | |
1335 | DONE; | |
1336 | }") | |
1337 | ||
13d39dbc | 1338 | ;;; pic symbol references |
d2a94ec0 TM |
1339 | |
1340 | (define_insn "" | |
1341 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1342 | (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") | |
1343 | (match_operand:SI 2 "symbolic_operand" ""))))] | |
1344 | "flag_pic && operands[1] == pic_offset_table_rtx" | |
1345 | "ldw T'%2(%1),%0" | |
1346 | [(set_attr "type" "load") | |
4c2164b7 | 1347 | (set_attr "length" "4")]) |
d2a94ec0 | 1348 | |
c733e074 | 1349 | (define_insn "" |
2f95ebc2 | 1350 | [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" |
7a8940aa | 1351 | "=r,r,r,r,r,Q,*q,!f,f,*TR") |
2f95ebc2 | 1352 | (match_operand:SI 1 "move_operand" |
2414e0e2 | 1353 | "r,J,N,K,RQ,rM,rM,!fM,*RT,f"))] |
925cf581 TG |
1354 | "(register_operand (operands[0], SImode) |
1355 | || reg_or_0_operand (operands[1], SImode)) | |
1356 | && ! TARGET_SOFT_FLOAT" | |
c733e074 | 1357 | "@ |
b16656f6 | 1358 | copy %1,%0 |
ac153498 | 1359 | ldi %1,%0 |
6f672dc0 | 1360 | ldil L'%1,%0 |
ac153498 | 1361 | zdepi %Z1,%0 |
c733e074 TM |
1362 | ldw%M1 %1,%0 |
1363 | stw%M0 %r1,%0 | |
cb524f44 | 1364 | mtsar %r1 |
4c1fcd13 | 1365 | fcpy,sgl %r1,%0 |
2414e0e2 JL |
1366 | fldw%F1 %1,%0 |
1367 | fstw%F0 %1,%0" | |
c47decad | 1368 | [(set_attr "type" "move,move,move,shift,load,store,move,fpalu,fpload,fpstore") |
c4bb6b38 | 1369 | (set_attr "pa_combine_type" "addmove") |
4c2164b7 | 1370 | (set_attr "length" "4,4,4,4,4,4,4,4,4,4")]) |
ac153498 | 1371 | |
925cf581 TG |
1372 | (define_insn "" |
1373 | [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" | |
1374 | "=r,r,r,r,r,Q,*q") | |
1375 | (match_operand:SI 1 "move_operand" | |
2414e0e2 | 1376 | "r,J,N,K,RQ,rM,rM"))] |
925cf581 TG |
1377 | "(register_operand (operands[0], SImode) |
1378 | || reg_or_0_operand (operands[1], SImode)) | |
1379 | && TARGET_SOFT_FLOAT" | |
1380 | "@ | |
1381 | copy %1,%0 | |
1382 | ldi %1,%0 | |
1383 | ldil L'%1,%0 | |
1384 | zdepi %Z1,%0 | |
1385 | ldw%M1 %1,%0 | |
1386 | stw%M0 %r1,%0 | |
1387 | mtsar %r1" | |
1388 | [(set_attr "type" "move,move,move,move,load,store,move") | |
c4bb6b38 | 1389 | (set_attr "pa_combine_type" "addmove") |
925cf581 TG |
1390 | (set_attr "length" "4,4,4,4,4,4,4")]) |
1391 | ||
31d4f31f JL |
1392 | (define_insn "" |
1393 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1394 | (mem:SI (plus:SI (match_operand:SI 1 "basereg_operand" "r") | |
1395 | (match_operand:SI 2 "register_operand" "r"))))] | |
1396 | "! TARGET_DISABLE_INDEXING" | |
1397 | "* | |
1398 | { | |
1399 | /* Reload can create backwards (relative to cse) unscaled index | |
1400 | address modes when eliminating registers and possibly for | |
1401 | pseudos that don't get hard registers. Deal with it. */ | |
1402 | if (operands[2] == hard_frame_pointer_rtx | |
1403 | || operands[2] == stack_pointer_rtx) | |
1404 | return \"ldwx %1(0,%2),%0\"; | |
1405 | else | |
1406 | return \"ldwx %2(0,%1),%0\"; | |
1407 | }" | |
1408 | [(set_attr "type" "load") | |
1409 | (set_attr "length" "4")]) | |
1410 | ||
68944452 JL |
1411 | (define_insn "" |
1412 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1413 | (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") | |
1414 | (match_operand:SI 2 "basereg_operand" "r"))))] | |
1415 | "! TARGET_DISABLE_INDEXING" | |
1416 | "* | |
1417 | { | |
1418 | /* Reload can create backwards (relative to cse) unscaled index | |
1419 | address modes when eliminating registers and possibly for | |
1420 | pseudos that don't get hard registers. Deal with it. */ | |
1421 | if (operands[1] == hard_frame_pointer_rtx | |
1422 | || operands[1] == stack_pointer_rtx) | |
1423 | return \"ldwx %2(0,%1),%0\"; | |
1424 | else | |
1425 | return \"ldwx %1(0,%2),%0\"; | |
1426 | }" | |
1427 | [(set_attr "type" "load") | |
1428 | (set_attr "length" "4")]) | |
1429 | ||
ac153498 TG |
1430 | ;; Load or store with base-register modification. |
1431 | ||
c1fab105 | 1432 | (define_insn "pre_ldwm" |
305123ba | 1433 | [(set (match_operand:SI 0 "register_operand" "=r") |
1b8b89f1 | 1434 | (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "+r") |
ac153498 | 1435 | (match_operand:SI 2 "pre_cint_operand" "")))) |
305123ba | 1436 | (set (match_dup 1) |
ac153498 TG |
1437 | (plus:SI (match_dup 1) (match_dup 2)))] |
1438 | "" | |
1439 | "* | |
1440 | { | |
1441 | if (INTVAL (operands[2]) < 0) | |
305123ba JL |
1442 | return \"ldwm %2(0,%1),%0\"; |
1443 | return \"ldws,mb %2(0,%1),%0\"; | |
ac153498 TG |
1444 | }" |
1445 | [(set_attr "type" "load") | |
4c2164b7 | 1446 | (set_attr "length" "4")]) |
ac153498 | 1447 | |
c1fab105 | 1448 | (define_insn "pre_stwm" |
1b8b89f1 | 1449 | [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "+r") |
305123ba JL |
1450 | (match_operand:SI 1 "pre_cint_operand" ""))) |
1451 | (match_operand:SI 2 "reg_or_0_operand" "rM")) | |
1452 | (set (match_dup 0) | |
1453 | (plus:SI (match_dup 0) (match_dup 1)))] | |
ac153498 TG |
1454 | "" |
1455 | "* | |
1456 | { | |
305123ba JL |
1457 | if (INTVAL (operands[1]) < 0) |
1458 | return \"stwm %r2,%1(0,%0)\"; | |
1459 | return \"stws,mb %r2,%1(0,%0)\"; | |
ac153498 TG |
1460 | }" |
1461 | [(set_attr "type" "store") | |
4c2164b7 | 1462 | (set_attr "length" "4")]) |
c733e074 | 1463 | |
c1fab105 | 1464 | (define_insn "post_ldwm" |
305123ba | 1465 | [(set (match_operand:SI 0 "register_operand" "=r") |
1b8b89f1 | 1466 | (mem:SI (match_operand:SI 1 "register_operand" "+r"))) |
1b84b6f8 JL |
1467 | (set (match_dup 1) |
1468 | (plus:SI (match_dup 1) | |
c1fab105 JL |
1469 | (match_operand:SI 2 "post_cint_operand" "")))] |
1470 | "" | |
1471 | "* | |
1472 | { | |
1473 | if (INTVAL (operands[2]) > 0) | |
305123ba | 1474 | return \"ldwm %2(0,%1),%0\"; |
1b84b6f8 | 1475 | return \"ldws,ma %2(0,%1),%0\"; |
c1fab105 JL |
1476 | }" |
1477 | [(set_attr "type" "load") | |
4c2164b7 | 1478 | (set_attr "length" "4")]) |
c1fab105 JL |
1479 | |
1480 | (define_insn "post_stwm" | |
1b8b89f1 | 1481 | [(set (mem:SI (match_operand:SI 0 "register_operand" "+r")) |
305123ba JL |
1482 | (match_operand:SI 1 "reg_or_0_operand" "rM")) |
1483 | (set (match_dup 0) | |
1484 | (plus:SI (match_dup 0) | |
c1fab105 JL |
1485 | (match_operand:SI 2 "post_cint_operand" "")))] |
1486 | "" | |
1487 | "* | |
1488 | { | |
1489 | if (INTVAL (operands[2]) > 0) | |
305123ba JL |
1490 | return \"stwm %r1,%2(0,%0)\"; |
1491 | return \"stws,ma %r1,%2(0,%0)\"; | |
c1fab105 JL |
1492 | }" |
1493 | [(set_attr "type" "store") | |
4c2164b7 | 1494 | (set_attr "length" "4")]) |
c1fab105 | 1495 | |
c733e074 | 1496 | ;; For pic |
6bb36601 JL |
1497 | ;; Note since this pattern can be created at reload time (via movsi), all |
1498 | ;; the same rules for movsi apply here. (no new pseudos, no temporaries). | |
1499 | (define_insn "pic_load_label" | |
1500 | [(set (match_operand:SI 0 "register_operand" "=a") | |
1501 | (match_operand:SI 1 "pic_label_operand" ""))] | |
c733e074 TM |
1502 | "" |
1503 | "* | |
1504 | { | |
1505 | rtx label_rtx = gen_label_rtx (); | |
1506 | rtx xoperands[3]; | |
1507 | extern FILE *asm_out_file; | |
1508 | ||
1509 | xoperands[0] = operands[0]; | |
1510 | xoperands[1] = operands[1]; | |
1511 | xoperands[2] = label_rtx; | |
6bb36601 JL |
1512 | output_asm_insn (\"bl .+8,%0\", xoperands); |
1513 | output_asm_insn (\"depi 0,31,2,%0\", xoperands); | |
1514 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", | |
1515 | CODE_LABEL_NUMBER (label_rtx)); | |
1516 | ||
1517 | /* If we're trying to load the address of a label that happens to be | |
1518 | close, then we can use a shorter sequence. */ | |
1519 | if (GET_CODE (operands[1]) == LABEL_REF | |
1520 | && insn_addresses | |
1521 | && abs (insn_addresses[INSN_UID (XEXP (operands[1], 0))] | |
8e84cfdd | 1522 | - insn_addresses[INSN_UID (insn)]) < 8100) |
6bb36601 JL |
1523 | { |
1524 | /* Prefixing with R% here is wrong, it extracts just 11 bits and is | |
1525 | always non-negative. */ | |
1526 | output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands); | |
1527 | } | |
1528 | else | |
1529 | { | |
1530 | output_asm_insn (\"addil L%%%1-%2,%0\", xoperands); | |
1531 | output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands); | |
1532 | } | |
c733e074 | 1533 | return \"\"; |
6bb36601 | 1534 | }" |
c733e074 | 1535 | [(set_attr "type" "multi") |
6bb36601 JL |
1536 | (set_attr "length" "16")]) ; 12 or 16 |
1537 | ||
a205e34b | 1538 | (define_insn "pic2_highpart" |
6bb36601 | 1539 | [(set (match_operand:SI 0 "register_operand" "=a") |
a205e34b JL |
1540 | (plus:SI (match_operand:SI 1 "register_operand" "r") |
1541 | (high:SI (match_operand 2 "" ""))))] | |
6bb36601 JL |
1542 | "symbolic_operand (operands[2], Pmode) |
1543 | && ! function_label_operand (operands[2]) | |
6bb36601 JL |
1544 | && flag_pic == 2" |
1545 | "addil LT'%G2,%1" | |
1546 | [(set_attr "type" "binary") | |
1547 | (set_attr "length" "4")]) | |
c733e074 | 1548 | |
a205e34b JL |
1549 | ; We need this to make sure CSE doesn't simplify a memory load with a |
1550 | ; symbolic address, whose content it think it knows. For PIC, what CSE | |
1551 | ; think is the real value will be the address of that value. | |
1552 | (define_insn "pic2_lo_sum" | |
1553 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1554 | (mem:SI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") | |
1555 | (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")] 0))))] | |
1556 | "" | |
1557 | "* | |
1558 | { | |
1559 | if (flag_pic != 2) | |
1560 | abort (); | |
1561 | return \"ldw RT'%G2(%1),%0\"; | |
c47decad JL |
1562 | }" |
1563 | [(set_attr "type" "load") | |
1564 | (set_attr "length" "4")]) | |
a205e34b JL |
1565 | |
1566 | ||
44552b6a JL |
1567 | ;; Always use addil rather than ldil;add sequences. This allows the |
1568 | ;; HP linker to eliminate the dp relocation if the symbolic operand | |
1569 | ;; lives in the TEXT space. | |
9c36061e JL |
1570 | (define_insn "" |
1571 | [(set (match_operand:SI 0 "register_operand" "=a") | |
9f309ba3 | 1572 | (high:SI (match_operand 1 "" "")))] |
2f95ebc2 | 1573 | "symbolic_operand (operands[1], Pmode) |
9f309ba3 | 1574 | && ! function_label_operand (operands[1]) |
6bb36601 JL |
1575 | && ! read_only_operand (operands[1]) |
1576 | && ! flag_pic" | |
c3d4f633 JL |
1577 | "* |
1578 | { | |
1579 | if (TARGET_LONG_LOAD_STORE) | |
1580 | return \"addil NLR'%H1,%%r27\;ldo N'%H1(%%r1),%%r1\"; | |
1581 | else | |
1582 | return \"addil LR'%H1,%%r27\"; | |
1583 | }" | |
9c36061e | 1584 | [(set_attr "type" "binary") |
c3d4f633 JL |
1585 | (set (attr "length") |
1586 | (if_then_else (eq (symbol_ref "TARGET_LONG_LOAD_STORE") (const_int 0)) | |
1587 | (const_int 4) | |
1588 | (const_int 8)))]) | |
1589 | ||
9c36061e | 1590 | |
2f95ebc2 | 1591 | ;; This is for use in the prologue/epilogue code. We need it |
c1fab105 JL |
1592 | ;; to add large constants to a stack pointer or frame pointer. |
1593 | ;; Because of the additional %r1 pressure, we probably do not | |
1594 | ;; want to use this in general code, so make it available | |
1595 | ;; only after reload. | |
1596 | (define_insn "add_high_const" | |
1597 | [(set (match_operand:SI 0 "register_operand" "=!a,*r") | |
3913f03a RK |
1598 | (plus:SI (match_operand:SI 1 "register_operand" "r,r") |
1599 | (high:SI (match_operand 2 "const_int_operand" ""))))] | |
c1fab105 JL |
1600 | "reload_completed" |
1601 | "@ | |
1602 | addil L'%G2,%1 | |
b16656f6 | 1603 | ldil L'%G2,%0\;addl %0,%1,%0" |
c1fab105 | 1604 | [(set_attr "type" "binary,binary") |
4c2164b7 | 1605 | (set_attr "length" "4,8")]) |
c1fab105 | 1606 | |
c733e074 TM |
1607 | (define_insn "" |
1608 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1609 | (high:SI (match_operand 1 "" "")))] | |
6bb36601 JL |
1610 | "(!flag_pic || !symbolic_operand (operands[1]), Pmode) |
1611 | && !is_function_label_plus_const (operands[1])" | |
65d5cba8 RK |
1612 | "* |
1613 | { | |
1614 | if (symbolic_operand (operands[1], Pmode)) | |
ad238e4b | 1615 | return \"ldil LR'%H1,%0\"; |
65d5cba8 RK |
1616 | else |
1617 | return \"ldil L'%G1,%0\"; | |
1618 | }" | |
c733e074 | 1619 | [(set_attr "type" "move") |
4c2164b7 | 1620 | (set_attr "length" "4")]) |
c733e074 | 1621 | |
c733e074 TM |
1622 | (define_insn "" |
1623 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1624 | (lo_sum:SI (match_operand:SI 1 "register_operand" "r") | |
907f67cc | 1625 | (match_operand:SI 2 "immediate_operand" "i")))] |
8d768fa2 | 1626 | "!is_function_label_plus_const (operands[2])" |
6bb36601 JL |
1627 | "* |
1628 | { | |
a205e34b | 1629 | if (flag_pic && symbolic_operand (operands[2], Pmode)) |
6bb36601 | 1630 | abort (); |
65d5cba8 RK |
1631 | else if (symbolic_operand (operands[2], Pmode)) |
1632 | return \"ldo RR'%G2(%1),%0\"; | |
6bb36601 JL |
1633 | else |
1634 | return \"ldo R'%G2(%1),%0\"; | |
1635 | }" | |
c47decad JL |
1636 | [(set_attr "type" "move") |
1637 | (set_attr "length" "4")]) | |
c733e074 | 1638 | |
26915fa9 JL |
1639 | ;; Now that a symbolic_address plus a constant is broken up early |
1640 | ;; in the compilation phase (for better CSE) we need a special | |
1641 | ;; combiner pattern to load the symbolic address plus the constant | |
2f95ebc2 | 1642 | ;; in only 2 instructions. (For cases where the symbolic address |
26915fa9 JL |
1643 | ;; was not a common subexpression.) |
1644 | (define_split | |
1645 | [(set (match_operand:SI 0 "register_operand" "") | |
b16656f6 | 1646 | (match_operand:SI 1 "symbolic_operand" "")) |
26915fa9 | 1647 | (clobber (match_operand:SI 2 "register_operand" ""))] |
6bb36601 | 1648 | "! (flag_pic && pic_label_operand (operands[1], SImode))" |
26915fa9 JL |
1649 | [(set (match_dup 2) (high:SI (match_dup 1))) |
1650 | (set (match_dup 0) (lo_sum:SI (match_dup 2) (match_dup 1)))] | |
1651 | "") | |
1652 | ||
78c0acfd JL |
1653 | ;; hppa_legitimize_address goes to a great deal of trouble to |
1654 | ;; create addresses which use indexing. In some cases, this | |
1655 | ;; is a lose because there isn't any store instructions which | |
1656 | ;; allow indexed addresses (with integer register source). | |
1657 | ;; | |
1658 | ;; These define_splits try to turn a 3 insn store into | |
1659 | ;; a 2 insn store with some creative RTL rewriting. | |
1660 | (define_split | |
1661 | [(set (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "") | |
1662 | (match_operand:SI 1 "shadd_operand" "")) | |
1663 | (plus:SI (match_operand:SI 2 "register_operand" "") | |
1664 | (match_operand:SI 3 "const_int_operand" "")))) | |
1665 | (match_operand:SI 4 "register_operand" "")) | |
1666 | (clobber (match_operand:SI 5 "register_operand" ""))] | |
1667 | "" | |
1668 | [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1)) | |
1669 | (match_dup 2))) | |
1670 | (set (mem:SI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))] | |
1671 | "") | |
1672 | ||
1673 | (define_split | |
1674 | [(set (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "") | |
1675 | (match_operand:SI 1 "shadd_operand" "")) | |
1676 | (plus:SI (match_operand:SI 2 "register_operand" "") | |
1677 | (match_operand:SI 3 "const_int_operand" "")))) | |
1678 | (match_operand:HI 4 "register_operand" "")) | |
1679 | (clobber (match_operand:SI 5 "register_operand" ""))] | |
1680 | "" | |
1681 | [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1)) | |
1682 | (match_dup 2))) | |
1683 | (set (mem:HI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))] | |
1684 | "") | |
1685 | ||
1686 | (define_split | |
1687 | [(set (mem:QI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "") | |
1688 | (match_operand:SI 1 "shadd_operand" "")) | |
1689 | (plus:SI (match_operand:SI 2 "register_operand" "") | |
1690 | (match_operand:SI 3 "const_int_operand" "")))) | |
1691 | (match_operand:QI 4 "register_operand" "")) | |
1692 | (clobber (match_operand:SI 5 "register_operand" ""))] | |
1693 | "" | |
1694 | [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1)) | |
1695 | (match_dup 2))) | |
1696 | (set (mem:QI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))] | |
1697 | "") | |
1698 | ||
c733e074 TM |
1699 | (define_expand "movhi" |
1700 | [(set (match_operand:HI 0 "general_operand" "") | |
1701 | (match_operand:HI 1 "general_operand" ""))] | |
1702 | "" | |
1703 | " | |
1704 | { | |
d2a94ec0 | 1705 | if (emit_move_sequence (operands, HImode, 0)) |
c733e074 TM |
1706 | DONE; |
1707 | }") | |
1708 | ||
1709 | (define_insn "" | |
0b27d5dd | 1710 | [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!f") |
2414e0e2 | 1711 | (match_operand:HI 1 "move_operand" "r,J,N,K,RQ,rM,rM,!fM"))] |
4d72c241 | 1712 | "register_operand (operands[0], HImode) |
29ed7081 | 1713 | || reg_or_0_operand (operands[1], HImode)" |
c733e074 | 1714 | "@ |
b16656f6 | 1715 | copy %1,%0 |
ac153498 | 1716 | ldi %1,%0 |
6f672dc0 | 1717 | ldil L'%1,%0 |
ac153498 | 1718 | zdepi %Z1,%0 |
c733e074 | 1719 | ldh%M1 %1,%0 |
d2a94ec0 | 1720 | sth%M0 %r1,%0 |
ac153498 | 1721 | mtsar %r1 |
222727e8 | 1722 | fcpy,sgl %r1,%0" |
c47decad | 1723 | [(set_attr "type" "move,move,move,shift,load,store,move,fpalu") |
c4bb6b38 | 1724 | (set_attr "pa_combine_type" "addmove") |
4c2164b7 | 1725 | (set_attr "length" "4,4,4,4,4,4,4,4")]) |
c733e074 | 1726 | |
31d4f31f JL |
1727 | (define_insn "" |
1728 | [(set (match_operand:HI 0 "register_operand" "=r") | |
1729 | (mem:HI (plus:SI (match_operand:SI 1 "basereg_operand" "r") | |
1730 | (match_operand:SI 2 "register_operand" "r"))))] | |
1731 | "! TARGET_DISABLE_INDEXING" | |
1732 | "* | |
1733 | { | |
1734 | /* Reload can create backwards (relative to cse) unscaled index | |
1735 | address modes when eliminating registers and possibly for | |
1736 | pseudos that don't get hard registers. Deal with it. */ | |
1737 | if (operands[2] == hard_frame_pointer_rtx | |
1738 | || operands[2] == stack_pointer_rtx) | |
1739 | return \"ldhx %1(0,%2),%0\"; | |
1740 | else | |
1741 | return \"ldhx %2(0,%1),%0\"; | |
1742 | }" | |
1743 | [(set_attr "type" "load") | |
1744 | (set_attr "length" "4")]) | |
1745 | ||
68944452 JL |
1746 | (define_insn "" |
1747 | [(set (match_operand:HI 0 "register_operand" "=r") | |
1748 | (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r") | |
1749 | (match_operand:SI 2 "basereg_operand" "r"))))] | |
1750 | "! TARGET_DISABLE_INDEXING" | |
1751 | "* | |
1752 | { | |
1753 | /* Reload can create backwards (relative to cse) unscaled index | |
1754 | address modes when eliminating registers and possibly for | |
1755 | pseudos that don't get hard registers. Deal with it. */ | |
1756 | if (operands[1] == hard_frame_pointer_rtx | |
1757 | || operands[1] == stack_pointer_rtx) | |
1758 | return \"ldhx %2(0,%1),%0\"; | |
1759 | else | |
1760 | return \"ldhx %1(0,%2),%0\"; | |
1761 | }" | |
1762 | [(set_attr "type" "load") | |
1763 | (set_attr "length" "4")]) | |
1764 | ||
31d4f31f JL |
1765 | ; Now zero extended variants. |
1766 | (define_insn "" | |
1767 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1768 | (zero_extend:SI (mem:HI | |
1769 | (plus:SI | |
1770 | (match_operand:SI 1 "basereg_operand" "r") | |
1771 | (match_operand:SI 2 "register_operand" "r")))))] | |
1772 | "! TARGET_DISABLE_INDEXING" | |
1773 | "* | |
1774 | { | |
1775 | /* Reload can create backwards (relative to cse) unscaled index | |
1776 | address modes when eliminating registers and possibly for | |
1777 | pseudos that don't get hard registers. Deal with it. */ | |
1778 | if (operands[2] == hard_frame_pointer_rtx | |
1779 | || operands[2] == stack_pointer_rtx) | |
1780 | return \"ldhx %1(0,%2),%0\"; | |
1781 | else | |
1782 | return \"ldhx %2(0,%1),%0\"; | |
1783 | }" | |
1784 | [(set_attr "type" "load") | |
1785 | (set_attr "length" "4")]) | |
1786 | ||
1787 | (define_insn "" | |
1788 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1789 | (zero_extend:SI (mem:HI | |
1790 | (plus:SI | |
1791 | (match_operand:SI 1 "register_operand" "r") | |
1792 | (match_operand:SI 2 "basereg_operand" "r")))))] | |
1793 | "! TARGET_DISABLE_INDEXING" | |
1794 | "* | |
1795 | { | |
1796 | /* Reload can create backwards (relative to cse) unscaled index | |
1797 | address modes when eliminating registers and possibly for | |
1798 | pseudos that don't get hard registers. Deal with it. */ | |
1799 | if (operands[1] == hard_frame_pointer_rtx | |
1800 | || operands[1] == stack_pointer_rtx) | |
1801 | return \"ldhx %2(0,%1),%0\"; | |
1802 | else | |
1803 | return \"ldhx %1(0,%2),%0\"; | |
1804 | }" | |
1805 | [(set_attr "type" "load") | |
1806 | (set_attr "length" "4")]) | |
1807 | ||
57b3a4f1 | 1808 | (define_insn "" |
305123ba | 1809 | [(set (match_operand:HI 0 "register_operand" "=r") |
1b8b89f1 | 1810 | (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "+r") |
ac153498 | 1811 | (match_operand:SI 2 "int5_operand" "L")))) |
305123ba | 1812 | (set (match_dup 1) |
ac153498 | 1813 | (plus:SI (match_dup 1) (match_dup 2)))] |
57b3a4f1 | 1814 | "" |
305123ba | 1815 | "ldhs,mb %2(0,%1),%0" |
ac153498 | 1816 | [(set_attr "type" "load") |
4c2164b7 | 1817 | (set_attr "length" "4")]) |
ac153498 | 1818 | |
31d4f31f JL |
1819 | ; And a zero extended variant. |
1820 | (define_insn "" | |
1821 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1822 | (zero_extend:SI (mem:HI | |
1823 | (plus:SI | |
1b8b89f1 | 1824 | (match_operand:SI 1 "register_operand" "+r") |
31d4f31f JL |
1825 | (match_operand:SI 2 "int5_operand" "L"))))) |
1826 | (set (match_dup 1) | |
1827 | (plus:SI (match_dup 1) (match_dup 2)))] | |
1828 | "" | |
1829 | "ldhs,mb %2(0,%1),%0" | |
1830 | [(set_attr "type" "load") | |
1831 | (set_attr "length" "4")]) | |
1832 | ||
ac153498 | 1833 | (define_insn "" |
1b8b89f1 | 1834 | [(set (mem:HI (plus:SI (match_operand:SI 0 "register_operand" "+r") |
305123ba JL |
1835 | (match_operand:SI 1 "int5_operand" "L"))) |
1836 | (match_operand:HI 2 "reg_or_0_operand" "rM")) | |
1837 | (set (match_dup 0) | |
1838 | (plus:SI (match_dup 0) (match_dup 1)))] | |
ac153498 | 1839 | "" |
305123ba | 1840 | "sths,mb %r2,%1(0,%0)" |
ac153498 | 1841 | [(set_attr "type" "store") |
4c2164b7 | 1842 | (set_attr "length" "4")]) |
ac153498 TG |
1843 | |
1844 | (define_insn "" | |
1845 | [(set (match_operand:HI 0 "register_operand" "=r") | |
6bb36601 JL |
1846 | (high:HI (match_operand 1 "const_int_operand" "")))] |
1847 | "" | |
ac153498 | 1848 | "ldil L'%G1,%0" |
57b3a4f1 | 1849 | [(set_attr "type" "move") |
4c2164b7 | 1850 | (set_attr "length" "4")]) |
57b3a4f1 | 1851 | |
c733e074 TM |
1852 | (define_insn "" |
1853 | [(set (match_operand:HI 0 "register_operand" "=r") | |
1854 | (lo_sum:HI (match_operand:HI 1 "register_operand" "r") | |
a205e34b | 1855 | (match_operand 2 "const_int_operand" "")))] |
c733e074 TM |
1856 | "" |
1857 | "ldo R'%G2(%1),%0" | |
c47decad JL |
1858 | [(set_attr "type" "move") |
1859 | (set_attr "length" "4")]) | |
c733e074 TM |
1860 | |
1861 | (define_expand "movqi" | |
1862 | [(set (match_operand:QI 0 "general_operand" "") | |
1863 | (match_operand:QI 1 "general_operand" ""))] | |
1864 | "" | |
1865 | " | |
1866 | { | |
d2a94ec0 | 1867 | if (emit_move_sequence (operands, QImode, 0)) |
c733e074 TM |
1868 | DONE; |
1869 | }") | |
1870 | ||
1871 | (define_insn "" | |
0b27d5dd | 1872 | [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!f") |
2414e0e2 | 1873 | (match_operand:QI 1 "move_operand" "r,J,N,K,RQ,rM,rM,!fM"))] |
4d72c241 | 1874 | "register_operand (operands[0], QImode) |
29ed7081 | 1875 | || reg_or_0_operand (operands[1], QImode)" |
c733e074 | 1876 | "@ |
b16656f6 | 1877 | copy %1,%0 |
ac153498 | 1878 | ldi %1,%0 |
6f672dc0 | 1879 | ldil L'%1,%0 |
ac153498 | 1880 | zdepi %Z1,%0 |
c733e074 | 1881 | ldb%M1 %1,%0 |
d2a94ec0 | 1882 | stb%M0 %r1,%0 |
ac153498 | 1883 | mtsar %r1 |
222727e8 | 1884 | fcpy,sgl %r1,%0" |
c47decad | 1885 | [(set_attr "type" "move,move,move,shift,load,store,move,fpalu") |
c4bb6b38 | 1886 | (set_attr "pa_combine_type" "addmove") |
4c2164b7 | 1887 | (set_attr "length" "4,4,4,4,4,4,4,4")]) |
c733e074 | 1888 | |
31d4f31f JL |
1889 | (define_insn "" |
1890 | [(set (match_operand:QI 0 "register_operand" "=r") | |
1891 | (mem:QI (plus:SI (match_operand:SI 1 "basereg_operand" "r") | |
1892 | (match_operand:SI 2 "register_operand" "r"))))] | |
1893 | "! TARGET_DISABLE_INDEXING" | |
1894 | "* | |
1895 | { | |
1896 | /* Reload can create backwards (relative to cse) unscaled index | |
1897 | address modes when eliminating registers and possibly for | |
1898 | pseudos that don't get hard registers. Deal with it. */ | |
1899 | if (operands[2] == hard_frame_pointer_rtx | |
1900 | || operands[2] == stack_pointer_rtx) | |
1901 | return \"ldbx %1(0,%2),%0\"; | |
1902 | else | |
1903 | return \"ldbx %2(0,%1),%0\"; | |
1904 | }" | |
1905 | [(set_attr "type" "load") | |
1906 | (set_attr "length" "4")]) | |
1907 | ||
68944452 JL |
1908 | (define_insn "" |
1909 | [(set (match_operand:QI 0 "register_operand" "=r") | |
1910 | (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r") | |
1911 | (match_operand:SI 2 "basereg_operand" "r"))))] | |
1912 | "! TARGET_DISABLE_INDEXING" | |
1913 | "* | |
1914 | { | |
1915 | /* Reload can create backwards (relative to cse) unscaled index | |
1916 | address modes when eliminating registers and possibly for | |
1917 | pseudos that don't get hard registers. Deal with it. */ | |
1918 | if (operands[1] == hard_frame_pointer_rtx | |
1919 | || operands[1] == stack_pointer_rtx) | |
1920 | return \"ldbx %2(0,%1),%0\"; | |
1921 | else | |
1922 | return \"ldbx %1(0,%2),%0\"; | |
1923 | }" | |
1924 | [(set_attr "type" "load") | |
1925 | (set_attr "length" "4")]) | |
1926 | ||
31d4f31f JL |
1927 | ; Indexed byte load with zero extension to SImode or HImode. |
1928 | (define_insn "" | |
1929 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1930 | (zero_extend:SI (mem:QI | |
1931 | (plus:SI | |
1932 | (match_operand:SI 1 "basereg_operand" "r") | |
1933 | (match_operand:SI 2 "register_operand" "r")))))] | |
1934 | "! TARGET_DISABLE_INDEXING" | |
1935 | "* | |
1936 | { | |
1937 | /* Reload can create backwards (relative to cse) unscaled index | |
1938 | address modes when eliminating registers and possibly for | |
1939 | pseudos that don't get hard registers. Deal with it. */ | |
1940 | if (operands[2] == hard_frame_pointer_rtx | |
1941 | || operands[2] == stack_pointer_rtx) | |
1942 | return \"ldbx %1(0,%2),%0\"; | |
1943 | else | |
1944 | return \"ldbx %2(0,%1),%0\"; | |
1945 | }" | |
1946 | [(set_attr "type" "load") | |
1947 | (set_attr "length" "4")]) | |
1948 | ||
1949 | (define_insn "" | |
1950 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1951 | (zero_extend:SI (mem:QI | |
1952 | (plus:SI | |
1953 | (match_operand:SI 1 "register_operand" "r") | |
1954 | (match_operand:SI 2 "basereg_operand" "r")))))] | |
1955 | "! TARGET_DISABLE_INDEXING" | |
1956 | "* | |
1957 | { | |
1958 | /* Reload can create backwards (relative to cse) unscaled index | |
1959 | address modes when eliminating registers and possibly for | |
1960 | pseudos that don't get hard registers. Deal with it. */ | |
1961 | if (operands[1] == hard_frame_pointer_rtx | |
1962 | || operands[1] == stack_pointer_rtx) | |
1963 | return \"ldbx %2(0,%1),%0\"; | |
1964 | else | |
1965 | return \"ldbx %1(0,%2),%0\"; | |
1966 | }" | |
1967 | [(set_attr "type" "load") | |
1968 | (set_attr "length" "4")]) | |
1969 | ||
1970 | (define_insn "" | |
1971 | [(set (match_operand:HI 0 "register_operand" "=r") | |
1972 | (zero_extend:HI (mem:QI | |
1973 | (plus:SI | |
1974 | (match_operand:SI 1 "basereg_operand" "r") | |
1975 | (match_operand:SI 2 "register_operand" "r")))))] | |
1976 | "! TARGET_DISABLE_INDEXING" | |
1977 | "* | |
1978 | { | |
1979 | /* Reload can create backwards (relative to cse) unscaled index | |
1980 | address modes when eliminating registers and possibly for | |
1981 | pseudos that don't get hard registers. Deal with it. */ | |
1982 | if (operands[2] == hard_frame_pointer_rtx | |
1983 | || operands[2] == stack_pointer_rtx) | |
1984 | return \"ldbx %1(0,%2),%0\"; | |
1985 | else | |
1986 | return \"ldbx %2(0,%1),%0\"; | |
1987 | }" | |
1988 | [(set_attr "type" "load") | |
1989 | (set_attr "length" "4")]) | |
1990 | ||
1991 | (define_insn "" | |
1992 | [(set (match_operand:HI 0 "register_operand" "=r") | |
1993 | (zero_extend:HI (mem:QI | |
1994 | (plus:SI | |
1995 | (match_operand:SI 1 "register_operand" "r") | |
1996 | (match_operand:SI 2 "basereg_operand" "r")))))] | |
1997 | "! TARGET_DISABLE_INDEXING" | |
1998 | "* | |
1999 | { | |
2000 | /* Reload can create backwards (relative to cse) unscaled index | |
2001 | address modes when eliminating registers and possibly for | |
2002 | pseudos that don't get hard registers. Deal with it. */ | |
2003 | if (operands[1] == hard_frame_pointer_rtx | |
2004 | || operands[1] == stack_pointer_rtx) | |
2005 | return \"ldbx %2(0,%1),%0\"; | |
2006 | else | |
2007 | return \"ldbx %1(0,%2),%0\"; | |
2008 | }" | |
2009 | [(set_attr "type" "load") | |
2010 | (set_attr "length" "4")]) | |
2011 | ||
c733e074 | 2012 | (define_insn "" |
305123ba | 2013 | [(set (match_operand:QI 0 "register_operand" "=r") |
1b8b89f1 | 2014 | (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "+r") |
ac153498 | 2015 | (match_operand:SI 2 "int5_operand" "L")))) |
305123ba | 2016 | (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))] |
c733e074 | 2017 | "" |
305123ba | 2018 | "ldbs,mb %2(0,%1),%0" |
b7a4467d | 2019 | [(set_attr "type" "load") |
4c2164b7 | 2020 | (set_attr "length" "4")]) |
d2a94ec0 | 2021 | |
31d4f31f JL |
2022 | ; Now the same thing with zero extensions. |
2023 | (define_insn "" | |
2024 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2025 | (zero_extend:SI (mem:QI (plus:SI | |
1b8b89f1 | 2026 | (match_operand:SI 1 "register_operand" "+r") |
31d4f31f JL |
2027 | (match_operand:SI 2 "int5_operand" "L"))))) |
2028 | (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))] | |
2029 | "" | |
2030 | "ldbs,mb %2(0,%1),%0" | |
2031 | [(set_attr "type" "load") | |
2032 | (set_attr "length" "4")]) | |
2033 | ||
2034 | (define_insn "" | |
2035 | [(set (match_operand:HI 0 "register_operand" "=r") | |
2036 | (zero_extend:HI (mem:QI (plus:SI | |
1b8b89f1 | 2037 | (match_operand:SI 1 "register_operand" "+r") |
31d4f31f JL |
2038 | (match_operand:SI 2 "int5_operand" "L"))))) |
2039 | (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))] | |
2040 | "" | |
2041 | "ldbs,mb %2(0,%1),%0" | |
2042 | [(set_attr "type" "load") | |
2043 | (set_attr "length" "4")]) | |
2044 | ||
d2a94ec0 | 2045 | (define_insn "" |
1b8b89f1 | 2046 | [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "+r") |
305123ba JL |
2047 | (match_operand:SI 1 "int5_operand" "L"))) |
2048 | (match_operand:QI 2 "reg_or_0_operand" "rM")) | |
2049 | (set (match_dup 0) | |
2050 | (plus:SI (match_dup 0) (match_dup 1)))] | |
ac153498 | 2051 | "" |
305123ba | 2052 | "stbs,mb %r2,%1(0,%0)" |
ac153498 | 2053 | [(set_attr "type" "store") |
4c2164b7 | 2054 | (set_attr "length" "4")]) |
d2a94ec0 | 2055 | |
c733e074 TM |
2056 | ;; The definition of this insn does not really explain what it does, |
2057 | ;; but it should suffice | |
2058 | ;; that anything generated as this insn will be recognized as one | |
2059 | ;; and that it will not successfully combine with anything. | |
2060 | (define_expand "movstrsi" | |
e9a25f70 JL |
2061 | [(parallel [(set (match_operand:BLK 0 "" "") |
2062 | (match_operand:BLK 1 "" "")) | |
2063 | (clobber (match_dup 7)) | |
2064 | (clobber (match_dup 8)) | |
907f67cc TG |
2065 | (clobber (match_dup 4)) |
2066 | (clobber (match_dup 5)) | |
e9a25f70 | 2067 | (clobber (match_dup 6)) |
c733e074 TM |
2068 | (use (match_operand:SI 2 "arith_operand" "")) |
2069 | (use (match_operand:SI 3 "const_int_operand" ""))])] | |
2070 | "" | |
2071 | " | |
2072 | { | |
68944452 | 2073 | int size, align; |
e9a25f70 | 2074 | |
68944452 JL |
2075 | /* HP provides very fast block move library routine for the PA; |
2076 | this routine includes: | |
2077 | ||
2078 | 4x4 byte at a time block moves, | |
2079 | 1x4 byte at a time with alignment checked at runtime with | |
2080 | attempts to align the source and destination as needed | |
2081 | 1x1 byte loop | |
2082 | ||
2083 | With that in mind, here's the heuristics to try and guess when | |
2084 | the inlined block move will be better than the library block | |
2085 | move: | |
2086 | ||
2087 | If the size isn't constant, then always use the library routines. | |
2088 | ||
2089 | If the size is large in respect to the known alignment, then use | |
2090 | the library routines. | |
2091 | ||
2092 | If the size is small in repsect to the known alignment, then open | |
2093 | code the copy (since that will lead to better scheduling). | |
2094 | ||
2095 | Else use the block move pattern. */ | |
2096 | ||
2097 | /* Undetermined size, use the library routine. */ | |
2098 | if (GET_CODE (operands[2]) != CONST_INT) | |
2099 | FAIL; | |
2100 | ||
2101 | size = INTVAL (operands[2]); | |
2102 | align = INTVAL (operands[3]); | |
2103 | align = align > 4 ? 4 : align; | |
2104 | ||
2105 | /* If size/alignment > 8 (eg size is large in respect to alignment), | |
2106 | then use the library routines. */ | |
e9a25f70 | 2107 | if (size / align > 16) |
68944452 | 2108 | FAIL; |
c733e074 | 2109 | |
68944452 | 2110 | /* This does happen, but not often enough to worry much about. */ |
e9a25f70 | 2111 | if (size / align < MOVE_RATIO) |
68944452 JL |
2112 | FAIL; |
2113 | ||
2114 | /* Fall through means we're going to use our block move pattern. */ | |
e9a25f70 JL |
2115 | operands[0] |
2116 | = change_address (operands[0], VOIDmode, | |
2117 | copy_to_mode_reg (SImode, XEXP (operands[0], 0))); | |
2118 | operands[1] | |
2119 | = change_address (operands[1], VOIDmode, | |
2120 | copy_to_mode_reg (SImode, XEXP (operands[1], 0))); | |
907f67cc TG |
2121 | operands[4] = gen_reg_rtx (SImode); |
2122 | operands[5] = gen_reg_rtx (SImode); | |
e9a25f70 JL |
2123 | operands[6] = gen_reg_rtx (SImode); |
2124 | operands[7] = XEXP (operands[0], 0); | |
2125 | operands[8] = XEXP (operands[1], 0); | |
c733e074 TM |
2126 | }") |
2127 | ||
2128 | ;; The operand constraints are written like this to support both compile-time | |
2129 | ;; and run-time determined byte count. If the count is run-time determined, | |
2130 | ;; the register with the byte count is clobbered by the copying code, and | |
2131 | ;; therefore it is forced to operand 2. If the count is compile-time | |
2132 | ;; determined, we need two scratch registers for the unrolled code. | |
68944452 | 2133 | (define_insn "movstrsi_internal" |
58939c25 TG |
2134 | [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r,r")) |
2135 | (mem:BLK (match_operand:SI 1 "register_operand" "+r,r"))) | |
c733e074 TM |
2136 | (clobber (match_dup 0)) |
2137 | (clobber (match_dup 1)) | |
907f67cc TG |
2138 | (clobber (match_operand:SI 2 "register_operand" "=r,r")) ;loop cnt/tmp |
2139 | (clobber (match_operand:SI 3 "register_operand" "=&r,&r")) ;item tmp | |
68944452 | 2140 | (clobber (match_operand:SI 6 "register_operand" "=&r,&r")) ;item tmp2 |
c733e074 TM |
2141 | (use (match_operand:SI 4 "arith_operand" "J,2")) ;byte count |
2142 | (use (match_operand:SI 5 "const_int_operand" "n,n"))] ;alignment | |
2143 | "" | |
2144 | "* return output_block_move (operands, !which_alternative);" | |
876662ef | 2145 | [(set_attr "type" "multi,multi")]) |
c733e074 TM |
2146 | \f |
2147 | ;; Floating point move insns | |
2148 | ||
2149 | ;; This pattern forces (set (reg:DF ...) (const_double ...)) | |
ae98fe09 RS |
2150 | ;; to be reloaded by putting the constant into memory when |
2151 | ;; reg is a floating point register. | |
2152 | ;; | |
2153 | ;; For integer registers we use ldil;ldo to set the appropriate | |
2154 | ;; value. | |
2f95ebc2 | 2155 | ;; |
ae98fe09 RS |
2156 | ;; This must come before the movdf pattern, and it must be present |
2157 | ;; to handle obscure reloading cases. | |
c733e074 | 2158 | (define_insn "" |
cda0f51e | 2159 | [(set (match_operand:DF 0 "register_operand" "=?r,f") |
925cf581 | 2160 | (match_operand:DF 1 "" "?F,m"))] |
222727e8 | 2161 | "GET_CODE (operands[1]) == CONST_DOUBLE |
925cf581 TG |
2162 | && operands[1] != CONST0_RTX (DFmode) |
2163 | && ! TARGET_SOFT_FLOAT" | |
ae98fe09 | 2164 | "* return (which_alternative == 0 ? output_move_double (operands) |
2414e0e2 | 2165 | : \"fldd%F1 %1,%0\");" |
ae98fe09 | 2166 | [(set_attr "type" "move,fpload") |
4c2164b7 | 2167 | (set_attr "length" "16,4")]) |
c733e074 TM |
2168 | |
2169 | (define_expand "movdf" | |
2170 | [(set (match_operand:DF 0 "general_operand" "") | |
2171 | (match_operand:DF 1 "general_operand" ""))] | |
2172 | "" | |
2173 | " | |
2174 | { | |
d2a94ec0 | 2175 | if (emit_move_sequence (operands, DFmode, 0)) |
c733e074 TM |
2176 | DONE; |
2177 | }") | |
2178 | ||
0fc4f911 RK |
2179 | ;; Reloading an SImode or DImode value requires a scratch register if |
2180 | ;; going in to or out of float point registers. | |
2181 | ||
2182 | (define_expand "reload_indf" | |
2183 | [(set (match_operand:DF 0 "register_operand" "=Z") | |
2184 | (match_operand:DF 1 "non_hard_reg_operand" "")) | |
2185 | (clobber (match_operand:DF 2 "register_operand" "=&r"))] | |
2186 | "" | |
2187 | " | |
2188 | { | |
2189 | if (emit_move_sequence (operands, DFmode, operands[2])) | |
2190 | DONE; | |
2191 | ||
2192 | /* We don't want the clobber emitted, so handle this ourselves. */ | |
2193 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); | |
2194 | DONE; | |
2195 | }") | |
2196 | ||
2197 | (define_expand "reload_outdf" | |
2198 | [(set (match_operand:DF 0 "non_hard_reg_operand" "") | |
2199 | (match_operand:DF 1 "register_operand" "Z")) | |
2200 | (clobber (match_operand:DF 2 "register_operand" "=&r"))] | |
2201 | "" | |
2202 | " | |
2203 | { | |
2204 | if (emit_move_sequence (operands, DFmode, operands[2])) | |
2205 | DONE; | |
2206 | ||
2207 | /* We don't want the clobber emitted, so handle this ourselves. */ | |
2208 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); | |
2209 | DONE; | |
2210 | }") | |
2211 | ||
c733e074 TM |
2212 | (define_insn "" |
2213 | [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" | |
2414e0e2 | 2214 | "=f,*r,RQ,?o,?Q,f,*r,*r") |
222727e8 | 2215 | (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" |
a89974a2 | 2216 | "fG,*rG,f,*r,*r,RQ,o,RQ"))] |
925cf581 TG |
2217 | "(register_operand (operands[0], DFmode) |
2218 | || reg_or_0_operand (operands[1], DFmode)) | |
d66dec28 JL |
2219 | && ! (GET_CODE (operands[1]) == CONST_DOUBLE |
2220 | && GET_CODE (operands[0]) == MEM) | |
925cf581 | 2221 | && ! TARGET_SOFT_FLOAT" |
c733e074 TM |
2222 | "* |
2223 | { | |
2f95ebc2 | 2224 | if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]) |
222727e8 | 2225 | || operands[1] == CONST0_RTX (DFmode)) |
c733e074 TM |
2226 | return output_fp_move_double (operands); |
2227 | return output_move_double (operands); | |
2228 | }" | |
9d53c942 JL |
2229 | [(set_attr "type" "fpalu,move,fpstore,store,store,fpload,load,load") |
2230 | (set_attr "length" "4,8,4,8,16,4,8,16")]) | |
c733e074 | 2231 | |
925cf581 TG |
2232 | (define_insn "" |
2233 | [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" | |
bad883f8 | 2234 | "=r,?o,?Q,r,r") |
925cf581 TG |
2235 | (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" |
2236 | "rG,r,r,o,Q"))] | |
2237 | "(register_operand (operands[0], DFmode) | |
2238 | || reg_or_0_operand (operands[1], DFmode)) | |
2239 | && TARGET_SOFT_FLOAT" | |
2240 | "* | |
2241 | { | |
2242 | return output_move_double (operands); | |
2243 | }" | |
2244 | [(set_attr "type" "move,store,store,load,load") | |
2245 | (set_attr "length" "8,8,16,8,16")]) | |
2246 | ||
31d4f31f JL |
2247 | (define_insn "" |
2248 | [(set (match_operand:DF 0 "register_operand" "=fx") | |
2249 | (mem:DF (plus:SI (match_operand:SI 1 "basereg_operand" "r") | |
2250 | (match_operand:SI 2 "register_operand" "r"))))] | |
2251 | "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" | |
2252 | "* | |
2253 | { | |
2254 | /* Reload can create backwards (relative to cse) unscaled index | |
2255 | address modes when eliminating registers and possibly for | |
2256 | pseudos that don't get hard registers. Deal with it. */ | |
2257 | if (operands[2] == hard_frame_pointer_rtx | |
2258 | || operands[2] == stack_pointer_rtx) | |
2259 | return \"flddx %1(0,%2),%0\"; | |
2260 | else | |
2261 | return \"flddx %2(0,%1),%0\"; | |
2262 | }" | |
2263 | [(set_attr "type" "fpload") | |
2264 | (set_attr "length" "4")]) | |
2265 | ||
68944452 JL |
2266 | (define_insn "" |
2267 | [(set (match_operand:DF 0 "register_operand" "=fx") | |
2268 | (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "r") | |
2269 | (match_operand:SI 2 "basereg_operand" "r"))))] | |
2270 | "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" | |
2271 | "* | |
2272 | { | |
2273 | /* Reload can create backwards (relative to cse) unscaled index | |
2274 | address modes when eliminating registers and possibly for | |
2275 | pseudos that don't get hard registers. Deal with it. */ | |
2276 | if (operands[1] == hard_frame_pointer_rtx | |
2277 | || operands[1] == stack_pointer_rtx) | |
2278 | return \"flddx %2(0,%1),%0\"; | |
2279 | else | |
2280 | return \"flddx %1(0,%2),%0\"; | |
2281 | }" | |
2282 | [(set_attr "type" "fpload") | |
2283 | (set_attr "length" "4")]) | |
2284 | ||
31d4f31f JL |
2285 | (define_insn "" |
2286 | [(set (mem:DF (plus:SI (match_operand:SI 1 "basereg_operand" "r") | |
2287 | (match_operand:SI 2 "register_operand" "r"))) | |
2288 | (match_operand:DF 0 "register_operand" "fx"))] | |
2289 | "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" | |
2290 | "* | |
2291 | { | |
2292 | /* Reload can create backwards (relative to cse) unscaled index | |
2293 | address modes when eliminating registers and possibly for | |
2294 | pseudos that don't get hard registers. Deal with it. */ | |
2295 | if (operands[2] == hard_frame_pointer_rtx | |
2296 | || operands[2] == stack_pointer_rtx) | |
2297 | return \"fstdx %0,%1(0,%2)\"; | |
2298 | else | |
2299 | return \"fstdx %0,%2(0,%1)\"; | |
2300 | }" | |
2301 | [(set_attr "type" "fpstore") | |
2302 | (set_attr "length" "4")]) | |
2303 | ||
68944452 JL |
2304 | (define_insn "" |
2305 | [(set (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "r") | |
2306 | (match_operand:SI 2 "basereg_operand" "r"))) | |
2307 | (match_operand:DF 0 "register_operand" "fx"))] | |
2308 | "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" | |
2309 | "* | |
2310 | { | |
2311 | /* Reload can create backwards (relative to cse) unscaled index | |
2312 | address modes when eliminating registers and possibly for | |
2313 | pseudos that don't get hard registers. Deal with it. */ | |
2314 | if (operands[1] == hard_frame_pointer_rtx | |
2315 | || operands[1] == stack_pointer_rtx) | |
2316 | return \"fstdx %0,%2(0,%1)\"; | |
2317 | else | |
2318 | return \"fstdx %0,%1(0,%2)\"; | |
2319 | }" | |
2320 | [(set_attr "type" "fpstore") | |
2321 | (set_attr "length" "4")]) | |
2322 | ||
c733e074 TM |
2323 | (define_expand "movdi" |
2324 | [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") | |
2325 | (match_operand:DI 1 "general_operand" ""))] | |
2326 | "" | |
2327 | " | |
2328 | { | |
d2a94ec0 | 2329 | if (emit_move_sequence (operands, DImode, 0)) |
c733e074 TM |
2330 | DONE; |
2331 | }") | |
2332 | ||
0fc4f911 RK |
2333 | (define_expand "reload_indi" |
2334 | [(set (match_operand:DI 0 "register_operand" "=f") | |
2335 | (match_operand:DI 1 "non_hard_reg_operand" "")) | |
2336 | (clobber (match_operand:SI 2 "register_operand" "=&r"))] | |
2337 | "" | |
2338 | " | |
2339 | { | |
2340 | if (emit_move_sequence (operands, DImode, operands[2])) | |
2341 | DONE; | |
2342 | ||
2343 | /* We don't want the clobber emitted, so handle this ourselves. */ | |
2344 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); | |
2345 | DONE; | |
2346 | }") | |
2347 | ||
2348 | (define_expand "reload_outdi" | |
2349 | [(set (match_operand:DI 0 "general_operand" "") | |
2350 | (match_operand:DI 1 "register_operand" "f")) | |
2351 | (clobber (match_operand:SI 2 "register_operand" "=&r"))] | |
2352 | "" | |
2353 | " | |
2354 | { | |
2355 | if (emit_move_sequence (operands, DImode, operands[2])) | |
2356 | DONE; | |
2357 | ||
2358 | /* We don't want the clobber emitted, so handle this ourselves. */ | |
2359 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); | |
2360 | DONE; | |
2361 | }") | |
2362 | ||
53a66787 TG |
2363 | (define_insn "" |
2364 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2365 | (high:DI (match_operand 1 "" "")))] | |
6bb36601 | 2366 | "" |
53a66787 TG |
2367 | "* |
2368 | { | |
2369 | rtx op0 = operands[0]; | |
2370 | rtx op1 = operands[1]; | |
2371 | ||
2372 | if (GET_CODE (op1) == CONST_INT) | |
2373 | { | |
2374 | operands[0] = operand_subword (op0, 1, 0, DImode); | |
2375 | output_asm_insn (\"ldil L'%1,%0\", operands); | |
2376 | ||
2377 | operands[0] = operand_subword (op0, 0, 0, DImode); | |
2378 | if (INTVAL (op1) < 0) | |
ac153498 | 2379 | output_asm_insn (\"ldi -1,%0\", operands); |
53a66787 | 2380 | else |
ac153498 | 2381 | output_asm_insn (\"ldi 0,%0\", operands); |
876662ef | 2382 | return \"\"; |
53a66787 TG |
2383 | } |
2384 | else if (GET_CODE (op1) == CONST_DOUBLE) | |
2385 | { | |
2386 | operands[0] = operand_subword (op0, 1, 0, DImode); | |
5dee33ac | 2387 | operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1)); |
53a66787 TG |
2388 | output_asm_insn (\"ldil L'%1,%0\", operands); |
2389 | ||
2390 | operands[0] = operand_subword (op0, 0, 0, DImode); | |
5dee33ac | 2391 | operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1)); |
53a66787 | 2392 | output_asm_insn (singlemove_string (operands), operands); |
876662ef | 2393 | return \"\"; |
53a66787 TG |
2394 | } |
2395 | else | |
2396 | abort (); | |
2397 | }" | |
2398 | [(set_attr "type" "move") | |
4c2164b7 | 2399 | (set_attr "length" "8")]) |
53a66787 | 2400 | |
d2a94ec0 TM |
2401 | ;;; Experimental |
2402 | ||
c733e074 TM |
2403 | (define_insn "" |
2404 | [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" | |
7a8940aa | 2405 | "=r,o,Q,r,r,r,f,f,*TR") |
c733e074 | 2406 | (match_operand:DI 1 "general_operand" |
a89974a2 | 2407 | "rM,r,r,o*R,Q,i,fM,*TR,f"))] |
925cf581 TG |
2408 | "(register_operand (operands[0], DImode) |
2409 | || reg_or_0_operand (operands[1], DImode)) | |
2410 | && ! TARGET_SOFT_FLOAT" | |
c733e074 TM |
2411 | "* |
2412 | { | |
222727e8 JL |
2413 | if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]) |
2414 | || (operands[1] == CONST0_RTX (DImode))) | |
c733e074 TM |
2415 | return output_fp_move_double (operands); |
2416 | return output_move_double (operands); | |
2417 | }" | |
c47decad | 2418 | [(set_attr "type" "move,store,store,load,load,multi,fpalu,fpload,fpstore") |
9d53c942 | 2419 | (set_attr "length" "8,8,16,8,16,16,4,4,4")]) |
c733e074 | 2420 | |
925cf581 TG |
2421 | (define_insn "" |
2422 | [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" | |
bad883f8 | 2423 | "=r,o,Q,r,r,r") |
925cf581 TG |
2424 | (match_operand:DI 1 "general_operand" |
2425 | "rM,r,r,o,Q,i"))] | |
2426 | "(register_operand (operands[0], DImode) | |
2427 | || reg_or_0_operand (operands[1], DImode)) | |
2428 | && TARGET_SOFT_FLOAT" | |
2429 | "* | |
2430 | { | |
2431 | return output_move_double (operands); | |
2432 | }" | |
cc5c9c48 | 2433 | [(set_attr "type" "move,store,store,load,load,multi") |
925cf581 TG |
2434 | (set_attr "length" "8,8,16,8,16,16")]) |
2435 | ||
53a66787 | 2436 | (define_insn "" |
d13a220a | 2437 | [(set (match_operand:DI 0 "register_operand" "=r,&r") |
53a66787 | 2438 | (lo_sum:DI (match_operand:DI 1 "register_operand" "0,r") |
907f67cc | 2439 | (match_operand:DI 2 "immediate_operand" "i,i")))] |
53a66787 TG |
2440 | "" |
2441 | "* | |
2442 | { | |
2443 | /* Don't output a 64 bit constant, since we can't trust the assembler to | |
2444 | handle it correctly. */ | |
2445 | if (GET_CODE (operands[2]) == CONST_DOUBLE) | |
5dee33ac | 2446 | operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2])); |
53a66787 TG |
2447 | if (which_alternative == 1) |
2448 | output_asm_insn (\"copy %1,%0\", operands); | |
2449 | return \"ldo R'%G2(%R1),%R0\"; | |
2450 | }" | |
c47decad JL |
2451 | [(set_attr "type" "move,move") |
2452 | (set_attr "length" "4,8")]) | |
53a66787 | 2453 | |
ae98fe09 RS |
2454 | ;; This pattern forces (set (reg:SF ...) (const_double ...)) |
2455 | ;; to be reloaded by putting the constant into memory when | |
2456 | ;; reg is a floating point register. | |
2457 | ;; | |
2458 | ;; For integer registers we use ldil;ldo to set the appropriate | |
2459 | ;; value. | |
2f95ebc2 | 2460 | ;; |
ae98fe09 RS |
2461 | ;; This must come before the movsf pattern, and it must be present |
2462 | ;; to handle obscure reloading cases. | |
2463 | (define_insn "" | |
cda0f51e | 2464 | [(set (match_operand:SF 0 "register_operand" "=?r,f") |
925cf581 | 2465 | (match_operand:SF 1 "" "?F,m"))] |
ae98fe09 | 2466 | "GET_CODE (operands[1]) == CONST_DOUBLE |
925cf581 TG |
2467 | && operands[1] != CONST0_RTX (SFmode) |
2468 | && ! TARGET_SOFT_FLOAT" | |
ae98fe09 | 2469 | "* return (which_alternative == 0 ? singlemove_string (operands) |
2414e0e2 | 2470 | : \" fldw%F1 %1,%0\");" |
ae98fe09 | 2471 | [(set_attr "type" "move,fpload") |
4c2164b7 | 2472 | (set_attr "length" "8,4")]) |
ae98fe09 | 2473 | |
c733e074 TM |
2474 | (define_expand "movsf" |
2475 | [(set (match_operand:SF 0 "general_operand" "") | |
2476 | (match_operand:SF 1 "general_operand" ""))] | |
2477 | "" | |
2478 | " | |
2479 | { | |
d2a94ec0 | 2480 | if (emit_move_sequence (operands, SFmode, 0)) |
c733e074 TM |
2481 | DONE; |
2482 | }") | |
2483 | ||
0fc4f911 RK |
2484 | ;; Reloading an SImode or DImode value requires a scratch register if |
2485 | ;; going in to or out of float point registers. | |
2486 | ||
2487 | (define_expand "reload_insf" | |
2488 | [(set (match_operand:SF 0 "register_operand" "=Z") | |
2489 | (match_operand:SF 1 "non_hard_reg_operand" "")) | |
2490 | (clobber (match_operand:SF 2 "register_operand" "=&r"))] | |
2491 | "" | |
2492 | " | |
2493 | { | |
2494 | if (emit_move_sequence (operands, SFmode, operands[2])) | |
2495 | DONE; | |
2496 | ||
2497 | /* We don't want the clobber emitted, so handle this ourselves. */ | |
2498 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); | |
2499 | DONE; | |
2500 | }") | |
2501 | ||
2502 | (define_expand "reload_outsf" | |
2503 | [(set (match_operand:SF 0 "non_hard_reg_operand" "") | |
2504 | (match_operand:SF 1 "register_operand" "Z")) | |
2505 | (clobber (match_operand:SF 2 "register_operand" "=&r"))] | |
2506 | "" | |
2507 | " | |
2508 | { | |
2509 | if (emit_move_sequence (operands, SFmode, operands[2])) | |
2510 | DONE; | |
2511 | ||
2512 | /* We don't want the clobber emitted, so handle this ourselves. */ | |
2513 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); | |
2514 | DONE; | |
2515 | }") | |
2516 | ||
c733e074 TM |
2517 | (define_insn "" |
2518 | [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" | |
2414e0e2 | 2519 | "=f,r,f,r,RQ,Q") |
222727e8 | 2520 | (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand" |
7a8940aa | 2521 | "fG,rG,RQ,RQ,f,rG"))] |
925cf581 TG |
2522 | "(register_operand (operands[0], SFmode) |
2523 | || reg_or_0_operand (operands[1], SFmode)) | |
2524 | && ! TARGET_SOFT_FLOAT" | |
c733e074 | 2525 | "@ |
222727e8 JL |
2526 | fcpy,sgl %r1,%0 |
2527 | copy %r1,%0 | |
2414e0e2 | 2528 | fldw%F1 %1,%0 |
c733e074 | 2529 | ldw%M1 %1,%0 |
2414e0e2 | 2530 | fstw%F0 %r1,%0 |
c733e074 | 2531 | stw%M0 %r1,%0" |
04e1baee | 2532 | [(set_attr "type" "fpalu,move,fpload,load,fpstore,store") |
c4bb6b38 | 2533 | (set_attr "pa_combine_type" "addmove") |
4c2164b7 | 2534 | (set_attr "length" "4,4,4,4,4,4")]) |
1d01c176 | 2535 | |
925cf581 TG |
2536 | (define_insn "" |
2537 | [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" | |
2538 | "=r,r,Q") | |
2539 | (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand" | |
7a8940aa | 2540 | "rG,RQ,rG"))] |
925cf581 TG |
2541 | "(register_operand (operands[0], SFmode) |
2542 | || reg_or_0_operand (operands[1], SFmode)) | |
2543 | && TARGET_SOFT_FLOAT" | |
2544 | "@ | |
2545 | copy %r1,%0 | |
2546 | ldw%M1 %1,%0 | |
2547 | stw%M0 %r1,%0" | |
2548 | [(set_attr "type" "move,load,store") | |
c4bb6b38 | 2549 | (set_attr "pa_combine_type" "addmove") |
925cf581 TG |
2550 | (set_attr "length" "4,4,4")]) |
2551 | ||
31d4f31f JL |
2552 | (define_insn "" |
2553 | [(set (match_operand:SF 0 "register_operand" "=fx") | |
2554 | (mem:SF (plus:SI (match_operand:SI 1 "basereg_operand" "r") | |
2555 | (match_operand:SI 2 "register_operand" "r"))))] | |
2556 | "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" | |
2557 | "* | |
2558 | { | |
2559 | /* Reload can create backwards (relative to cse) unscaled index | |
2560 | address modes when eliminating registers and possibly for | |
2561 | pseudos that don't get hard registers. Deal with it. */ | |
2562 | if (operands[2] == hard_frame_pointer_rtx | |
2563 | || operands[2] == stack_pointer_rtx) | |
2564 | return \"fldwx %1(0,%2),%0\"; | |
2565 | else | |
2566 | return \"fldwx %2(0,%1),%0\"; | |
2567 | }" | |
2568 | [(set_attr "type" "fpload") | |
2569 | (set_attr "length" "4")]) | |
2570 | ||
68944452 JL |
2571 | (define_insn "" |
2572 | [(set (match_operand:SF 0 "register_operand" "=fx") | |
2573 | (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "r") | |
2574 | (match_operand:SI 2 "basereg_operand" "r"))))] | |
2575 | "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" | |
2576 | "* | |
2577 | { | |
2578 | /* Reload can create backwards (relative to cse) unscaled index | |
2579 | address modes when eliminating registers and possibly for | |
2580 | pseudos that don't get hard registers. Deal with it. */ | |
2581 | if (operands[1] == hard_frame_pointer_rtx | |
2582 | || operands[1] == stack_pointer_rtx) | |
2583 | return \"fldwx %2(0,%1),%0\"; | |
2584 | else | |
2585 | return \"fldwx %1(0,%2),%0\"; | |
2586 | }" | |
2587 | [(set_attr "type" "fpload") | |
2588 | (set_attr "length" "4")]) | |
2589 | ||
31d4f31f JL |
2590 | (define_insn "" |
2591 | [(set (mem:SF (plus:SI (match_operand:SI 1 "basereg_operand" "r") | |
2592 | (match_operand:SI 2 "register_operand" "r"))) | |
2593 | (match_operand:SF 0 "register_operand" "fx"))] | |
2594 | "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" | |
2595 | "* | |
2596 | { | |
2597 | /* Reload can create backwards (relative to cse) unscaled index | |
2598 | address modes when eliminating registers and possibly for | |
2599 | pseudos that don't get hard registers. Deal with it. */ | |
2600 | if (operands[2] == hard_frame_pointer_rtx | |
2601 | || operands[2] == stack_pointer_rtx) | |
2602 | return \"fstwx %0,%1(0,%2)\"; | |
2603 | else | |
2604 | return \"fstwx %0,%2(0,%1)\"; | |
2605 | }" | |
2606 | [(set_attr "type" "fpstore") | |
2607 | (set_attr "length" "4")]) | |
2608 | \f | |
68944452 JL |
2609 | (define_insn "" |
2610 | [(set (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "r") | |
2611 | (match_operand:SI 2 "basereg_operand" "r"))) | |
2612 | (match_operand:SF 0 "register_operand" "fx"))] | |
2613 | "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" | |
2614 | "* | |
2615 | { | |
2616 | /* Reload can create backwards (relative to cse) unscaled index | |
2617 | address modes when eliminating registers and possibly for | |
2618 | pseudos that don't get hard registers. Deal with it. */ | |
2619 | if (operands[1] == hard_frame_pointer_rtx | |
2620 | || operands[1] == stack_pointer_rtx) | |
2621 | return \"fstwx %0,%2(0,%1)\"; | |
2622 | else | |
2623 | return \"fstwx %0,%1(0,%2)\"; | |
2624 | }" | |
2625 | [(set_attr "type" "fpstore") | |
2626 | (set_attr "length" "4")]) | |
c733e074 | 2627 | \f |
68944452 | 2628 | |
c733e074 | 2629 | ;;- zero extension instructions |
44cfd512 JL |
2630 | ;; We have define_expand for zero extension patterns to make sure the |
2631 | ;; operands get loaded into registers. The define_insns accept | |
2632 | ;; memory operands. This gives us better overall code than just | |
2633 | ;; having a pattern that does or does not accept memory operands. | |
c733e074 | 2634 | |
44cfd512 JL |
2635 | (define_expand "zero_extendhisi2" |
2636 | [(set (match_operand:SI 0 "register_operand" "") | |
c733e074 | 2637 | (zero_extend:SI |
44cfd512 | 2638 | (match_operand:HI 1 "register_operand" "")))] |
c733e074 | 2639 | "" |
44cfd512 JL |
2640 | "") |
2641 | ||
2642 | (define_insn "" | |
2643 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2644 | (zero_extend:SI | |
2645 | (match_operand:HI 1 "move_operand" "r,RQ")))] | |
2646 | "GET_CODE (operands[1]) != CONST_INT" | |
c733e074 TM |
2647 | "@ |
2648 | extru %1,31,16,%0 | |
2649 | ldh%M1 %1,%0" | |
c47decad JL |
2650 | [(set_attr "type" "shift,load") |
2651 | (set_attr "length" "4,4")]) | |
c733e074 | 2652 | |
44cfd512 JL |
2653 | (define_expand "zero_extendqihi2" |
2654 | [(set (match_operand:HI 0 "register_operand" "") | |
c733e074 | 2655 | (zero_extend:HI |
44cfd512 | 2656 | (match_operand:QI 1 "register_operand" "")))] |
c733e074 | 2657 | "" |
44cfd512 JL |
2658 | "") |
2659 | ||
2660 | (define_insn "" | |
2661 | [(set (match_operand:HI 0 "register_operand" "=r,r") | |
2662 | (zero_extend:HI | |
2663 | (match_operand:QI 1 "move_operand" "r,RQ")))] | |
2664 | "GET_CODE (operands[1]) != CONST_INT" | |
c733e074 TM |
2665 | "@ |
2666 | extru %1,31,8,%0 | |
2667 | ldb%M1 %1,%0" | |
c47decad JL |
2668 | [(set_attr "type" "shift,load") |
2669 | (set_attr "length" "4,4")]) | |
c733e074 | 2670 | |
44cfd512 JL |
2671 | (define_expand "zero_extendqisi2" |
2672 | [(set (match_operand:SI 0 "register_operand" "") | |
c733e074 | 2673 | (zero_extend:SI |
44cfd512 | 2674 | (match_operand:QI 1 "register_operand" "")))] |
c733e074 | 2675 | "" |
44cfd512 JL |
2676 | "") |
2677 | ||
2678 | (define_insn "" | |
2679 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2680 | (zero_extend:SI | |
2681 | (match_operand:QI 1 "move_operand" "r,RQ")))] | |
2682 | "GET_CODE (operands[1]) != CONST_INT" | |
c733e074 TM |
2683 | "@ |
2684 | extru %1,31,8,%0 | |
2685 | ldb%M1 %1,%0" | |
c47decad JL |
2686 | [(set_attr "type" "shift,load") |
2687 | (set_attr "length" "4,4")]) | |
6f672dc0 | 2688 | |
c733e074 | 2689 | ;;- sign extension instructions |
c733e074 TM |
2690 | |
2691 | (define_insn "extendhisi2" | |
2692 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2693 | (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] | |
2694 | "" | |
2695 | "extrs %1,31,16,%0" | |
c47decad JL |
2696 | [(set_attr "type" "shift") |
2697 | (set_attr "length" "4")]) | |
c733e074 TM |
2698 | |
2699 | (define_insn "extendqihi2" | |
2700 | [(set (match_operand:HI 0 "register_operand" "=r") | |
2701 | (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] | |
2702 | "" | |
2703 | "extrs %1,31,8,%0" | |
c47decad JL |
2704 | [(set_attr "type" "shift") |
2705 | (set_attr "length" "4")]) | |
c733e074 TM |
2706 | |
2707 | (define_insn "extendqisi2" | |
2708 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2709 | (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] | |
2710 | "" | |
2711 | "extrs %1,31,8,%0" | |
c47decad JL |
2712 | [(set_attr "type" "shift") |
2713 | (set_attr "length" "4")]) | |
c733e074 TM |
2714 | \f |
2715 | ;; Conversions between float and double. | |
2716 | ||
2717 | (define_insn "extendsfdf2" | |
0b27d5dd | 2718 | [(set (match_operand:DF 0 "register_operand" "=f") |
c733e074 | 2719 | (float_extend:DF |
0b27d5dd | 2720 | (match_operand:SF 1 "register_operand" "f")))] |
925cf581 | 2721 | "! TARGET_SOFT_FLOAT" |
c733e074 | 2722 | "fcnvff,sgl,dbl %1,%0" |
c47decad JL |
2723 | [(set_attr "type" "fpalu") |
2724 | (set_attr "length" "4")]) | |
c733e074 TM |
2725 | |
2726 | (define_insn "truncdfsf2" | |
0b27d5dd | 2727 | [(set (match_operand:SF 0 "register_operand" "=f") |
c733e074 | 2728 | (float_truncate:SF |
0b27d5dd | 2729 | (match_operand:DF 1 "register_operand" "f")))] |
925cf581 | 2730 | "! TARGET_SOFT_FLOAT" |
c733e074 | 2731 | "fcnvff,dbl,sgl %1,%0" |
c47decad JL |
2732 | [(set_attr "type" "fpalu") |
2733 | (set_attr "length" "4")]) | |
c733e074 TM |
2734 | |
2735 | ;; Conversion between fixed point and floating point. | |
2736 | ;; Note that among the fix-to-float insns | |
2737 | ;; the ones that start with SImode come first. | |
2738 | ;; That is so that an operand that is a CONST_INT | |
2739 | ;; (and therefore lacks a specific machine mode). | |
2740 | ;; will be recognized as SImode (which is always valid) | |
2741 | ;; rather than as QImode or HImode. | |
2742 | ||
2743 | ;; This pattern forces (set (reg:SF ...) (float:SF (const_int ...))) | |
2744 | ;; to be reloaded by putting the constant into memory. | |
2745 | ;; It must come before the more general floatsisf2 pattern. | |
2746 | (define_insn "" | |
cda0f51e | 2747 | [(set (match_operand:SF 0 "register_operand" "=f") |
c733e074 | 2748 | (float:SF (match_operand:SI 1 "const_int_operand" "m")))] |
925cf581 | 2749 | "! TARGET_SOFT_FLOAT" |
2414e0e2 | 2750 | "fldw%F1 %1,%0\;fcnvxf,sgl,sgl %0,%0" |
c733e074 | 2751 | [(set_attr "type" "fpalu") |
4c2164b7 | 2752 | (set_attr "length" "8")]) |
c733e074 TM |
2753 | |
2754 | (define_insn "floatsisf2" | |
cda0f51e | 2755 | [(set (match_operand:SF 0 "register_operand" "=f") |
0b27d5dd | 2756 | (float:SF (match_operand:SI 1 "register_operand" "f")))] |
925cf581 | 2757 | "! TARGET_SOFT_FLOAT" |
cb524f44 | 2758 | "fcnvxf,sgl,sgl %1,%0" |
c47decad JL |
2759 | [(set_attr "type" "fpalu") |
2760 | (set_attr "length" "4")]) | |
c733e074 TM |
2761 | |
2762 | ;; This pattern forces (set (reg:DF ...) (float:DF (const_int ...))) | |
2763 | ;; to be reloaded by putting the constant into memory. | |
2764 | ;; It must come before the more general floatsidf2 pattern. | |
2765 | (define_insn "" | |
cda0f51e | 2766 | [(set (match_operand:DF 0 "register_operand" "=f") |
c733e074 | 2767 | (float:DF (match_operand:SI 1 "const_int_operand" "m")))] |
925cf581 | 2768 | "! TARGET_SOFT_FLOAT" |
2414e0e2 | 2769 | "fldw%F1 %1,%0\;fcnvxf,sgl,dbl %0,%0" |
c733e074 | 2770 | [(set_attr "type" "fpalu") |
4c2164b7 | 2771 | (set_attr "length" "8")]) |
c733e074 TM |
2772 | |
2773 | (define_insn "floatsidf2" | |
cda0f51e | 2774 | [(set (match_operand:DF 0 "register_operand" "=f") |
0b27d5dd | 2775 | (float:DF (match_operand:SI 1 "register_operand" "f")))] |
925cf581 | 2776 | "! TARGET_SOFT_FLOAT" |
cb524f44 | 2777 | "fcnvxf,sgl,dbl %1,%0" |
c47decad JL |
2778 | [(set_attr "type" "fpalu") |
2779 | (set_attr "length" "4")]) | |
cb524f44 TG |
2780 | |
2781 | (define_expand "floatunssisf2" | |
2782 | [(set (subreg:SI (match_dup 2) 1) | |
2783 | (match_operand:SI 1 "register_operand" "")) | |
2784 | (set (subreg:SI (match_dup 2) 0) | |
2785 | (const_int 0)) | |
d177a3ef | 2786 | (set (match_operand:SF 0 "register_operand" "") |
cb524f44 | 2787 | (float:SF (match_dup 2)))] |
925cf581 | 2788 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" |
cb524f44 TG |
2789 | "operands[2] = gen_reg_rtx (DImode);") |
2790 | ||
2791 | (define_expand "floatunssidf2" | |
2792 | [(set (subreg:SI (match_dup 2) 1) | |
2793 | (match_operand:SI 1 "register_operand" "")) | |
2794 | (set (subreg:SI (match_dup 2) 0) | |
2795 | (const_int 0)) | |
d177a3ef | 2796 | (set (match_operand:DF 0 "register_operand" "") |
cb524f44 | 2797 | (float:DF (match_dup 2)))] |
925cf581 | 2798 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" |
cb524f44 TG |
2799 | "operands[2] = gen_reg_rtx (DImode);") |
2800 | ||
2801 | (define_insn "floatdisf2" | |
cda0f51e | 2802 | [(set (match_operand:SF 0 "register_operand" "=f") |
0b27d5dd | 2803 | (float:SF (match_operand:DI 1 "register_operand" "f")))] |
925cf581 | 2804 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" |
cb524f44 | 2805 | "fcnvxf,dbl,sgl %1,%0" |
c47decad JL |
2806 | [(set_attr "type" "fpalu") |
2807 | (set_attr "length" "4")]) | |
cb524f44 TG |
2808 | |
2809 | (define_insn "floatdidf2" | |
cda0f51e | 2810 | [(set (match_operand:DF 0 "register_operand" "=f") |
0b27d5dd | 2811 | (float:DF (match_operand:DI 1 "register_operand" "f")))] |
925cf581 | 2812 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" |
cb524f44 | 2813 | "fcnvxf,dbl,dbl %1,%0" |
c47decad JL |
2814 | [(set_attr "type" "fpalu") |
2815 | (set_attr "length" "4")]) | |
c733e074 TM |
2816 | |
2817 | ;; Convert a float to an actual integer. | |
2818 | ;; Truncation is performed as part of the conversion. | |
2819 | ||
2820 | (define_insn "fix_truncsfsi2" | |
0b27d5dd TG |
2821 | [(set (match_operand:SI 0 "register_operand" "=f") |
2822 | (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] | |
925cf581 | 2823 | "! TARGET_SOFT_FLOAT" |
04e1baee | 2824 | "fcnvfxt,sgl,sgl %1,%0" |
c47decad JL |
2825 | [(set_attr "type" "fpalu") |
2826 | (set_attr "length" "4")]) | |
c733e074 TM |
2827 | |
2828 | (define_insn "fix_truncdfsi2" | |
0b27d5dd TG |
2829 | [(set (match_operand:SI 0 "register_operand" "=f") |
2830 | (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] | |
925cf581 | 2831 | "! TARGET_SOFT_FLOAT" |
04e1baee | 2832 | "fcnvfxt,dbl,sgl %1,%0" |
c47decad JL |
2833 | [(set_attr "type" "fpalu") |
2834 | (set_attr "length" "4")]) | |
c733e074 | 2835 | |
cb524f44 | 2836 | (define_insn "fix_truncsfdi2" |
0b27d5dd TG |
2837 | [(set (match_operand:DI 0 "register_operand" "=f") |
2838 | (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] | |
925cf581 | 2839 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" |
cb524f44 | 2840 | "fcnvfxt,sgl,dbl %1,%0" |
c47decad JL |
2841 | [(set_attr "type" "fpalu") |
2842 | (set_attr "length" "4")]) | |
cb524f44 TG |
2843 | |
2844 | (define_insn "fix_truncdfdi2" | |
0b27d5dd TG |
2845 | [(set (match_operand:DI 0 "register_operand" "=f") |
2846 | (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] | |
925cf581 | 2847 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" |
cb524f44 | 2848 | "fcnvfxt,dbl,dbl %1,%0" |
c47decad JL |
2849 | [(set_attr "type" "fpalu") |
2850 | (set_attr "length" "4")]) | |
c733e074 TM |
2851 | \f |
2852 | ;;- arithmetic instructions | |
2853 | ||
2854 | (define_insn "adddi3" | |
2855 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2856 | (plus:DI (match_operand:DI 1 "register_operand" "%r") | |
876662ef | 2857 | (match_operand:DI 2 "arith11_operand" "rI")))] |
c733e074 | 2858 | "" |
876662ef TG |
2859 | "* |
2860 | { | |
2861 | if (GET_CODE (operands[2]) == CONST_INT) | |
2862 | { | |
2863 | if (INTVAL (operands[2]) >= 0) | |
1a72c2b7 | 2864 | return \"addi %2,%R1,%R0\;addc %1,0,%0\"; |
876662ef | 2865 | else |
1a72c2b7 | 2866 | return \"addi %2,%R1,%R0\;subb %1,0,%0\"; |
876662ef TG |
2867 | } |
2868 | else | |
2869 | return \"add %R2,%R1,%R0\;addc %2,%1,%0\"; | |
2870 | }" | |
c47decad JL |
2871 | [(set_attr "type" "binary") |
2872 | (set_attr "length" "8")]) | |
c733e074 | 2873 | |
d5db6922 TG |
2874 | (define_insn "" |
2875 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2876 | (plus:SI (not:SI (match_operand:SI 1 "register_operand" "r")) | |
2877 | (match_operand:SI 2 "register_operand" "r")))] | |
2878 | "" | |
c47decad JL |
2879 | "uaddcm %2,%1,%0" |
2880 | [(set_attr "type" "binary") | |
2881 | (set_attr "length" "4")]) | |
d5db6922 | 2882 | |
08cddb03 JL |
2883 | ;; define_splits to optimize cases of adding a constant integer |
2884 | ;; to a register when the constant does not fit in 14 bits. */ | |
2885 | (define_split | |
2886 | [(set (match_operand:SI 0 "register_operand" "") | |
2887 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
2888 | (match_operand:SI 2 "const_int_operand" ""))) | |
2889 | (clobber (match_operand:SI 4 "register_operand" ""))] | |
2f95ebc2 | 2890 | "! cint_ok_for_move (INTVAL (operands[2])) |
ea9f550a | 2891 | && VAL_14_BITS_P (INTVAL (operands[2]) >> 1)" |
08cddb03 JL |
2892 | [(set (match_dup 4) (plus:SI (match_dup 1) (match_dup 2))) |
2893 | (set (match_dup 0) (plus:SI (match_dup 4) (match_dup 3)))] | |
2894 | " | |
2895 | { | |
2896 | int val = INTVAL (operands[2]); | |
2897 | int low = (val < 0) ? -0x2000 : 0x1fff; | |
2898 | int rest = val - low; | |
2899 | ||
2900 | operands[2] = GEN_INT (rest); | |
2901 | operands[3] = GEN_INT (low); | |
2902 | }") | |
2903 | ||
2904 | (define_split | |
2905 | [(set (match_operand:SI 0 "register_operand" "") | |
2906 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
2907 | (match_operand:SI 2 "const_int_operand" ""))) | |
2908 | (clobber (match_operand:SI 4 "register_operand" ""))] | |
2909 | "! cint_ok_for_move (INTVAL (operands[2]))" | |
2910 | [(set (match_dup 4) (match_dup 2)) | |
2911 | (set (match_dup 0) (plus:SI (mult:SI (match_dup 4) (match_dup 3)) | |
2912 | (match_dup 1)))] | |
2913 | " | |
2914 | { | |
bd1fd7fb | 2915 | HOST_WIDE_INT intval = INTVAL (operands[2]); |
08cddb03 | 2916 | |
b16656f6 | 2917 | /* Try dividing the constant by 2, then 4, and finally 8 to see |
08cddb03 | 2918 | if we can get a constant which can be loaded into a register |
141b2e9f JL |
2919 | in a single instruction (cint_ok_for_move). |
2920 | ||
2921 | If that fails, try to negate the constant and subtract it | |
2922 | from our input operand. */ | |
08cddb03 JL |
2923 | if (intval % 2 == 0 && cint_ok_for_move (intval / 2)) |
2924 | { | |
b16656f6 | 2925 | operands[2] = GEN_INT (intval / 2); |
08cddb03 JL |
2926 | operands[3] = GEN_INT (2); |
2927 | } | |
2928 | else if (intval % 4 == 0 && cint_ok_for_move (intval / 4)) | |
2929 | { | |
b16656f6 | 2930 | operands[2] = GEN_INT (intval / 4); |
08cddb03 JL |
2931 | operands[3] = GEN_INT (4); |
2932 | } | |
2933 | else if (intval % 8 == 0 && cint_ok_for_move (intval / 8)) | |
2934 | { | |
b16656f6 | 2935 | operands[2] = GEN_INT (intval / 8); |
08cddb03 JL |
2936 | operands[3] = GEN_INT (8); |
2937 | } | |
141b2e9f JL |
2938 | else if (cint_ok_for_move (-intval)) |
2939 | { | |
2940 | emit_insn (gen_rtx (SET, VOIDmode, operands[4], GEN_INT (-intval))); | |
2941 | emit_insn (gen_subsi3 (operands[0], operands[1], operands[4])); | |
2942 | DONE; | |
2943 | } | |
2f95ebc2 | 2944 | else |
08cddb03 JL |
2945 | FAIL; |
2946 | }") | |
2947 | ||
c733e074 TM |
2948 | (define_insn "addsi3" |
2949 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2950 | (plus:SI (match_operand:SI 1 "register_operand" "%r,r") | |
2951 | (match_operand:SI 2 "arith_operand" "r,J")))] | |
2952 | "" | |
2953 | "@ | |
b16656f6 | 2954 | addl %1,%2,%0 |
c47decad JL |
2955 | ldo %2(%1),%0" |
2956 | [(set_attr "type" "binary,binary") | |
c4bb6b38 | 2957 | (set_attr "pa_combine_type" "addmove") |
c47decad | 2958 | (set_attr "length" "4,4")]) |
c733e074 | 2959 | |
30a830e9 RK |
2960 | ;; Disgusting kludge to work around reload bugs with frame pointer |
2961 | ;; elimination. Similar to other magic reload patterns in the | |
2962 | ;; indexed memory operations. | |
2963 | (define_insn "" | |
2964 | [(set (match_operand:SI 0 "register_operand" "=&r") | |
2965 | (plus:SI (plus:SI (match_operand:SI 1 "register_operand" "%r") | |
2966 | (match_operand:SI 2 "register_operand" "r")) | |
2967 | (match_operand:SI 3 "const_int_operand" "rL")))] | |
2968 | "reload_in_progress" | |
2969 | "* | |
2970 | { | |
2971 | if (GET_CODE (operands[3]) == CONST_INT) | |
2972 | return \"ldo %3(%2),%0\;addl %1,%0,%0\"; | |
2973 | else | |
2974 | return \"addl %3,%2,%0\;addl %1,%0,%0\"; | |
2975 | }" | |
2976 | [(set_attr "type" "binary") | |
2977 | (set_attr "length" "8")]) | |
2978 | ||
c733e074 TM |
2979 | (define_insn "subdi3" |
2980 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2981 | (minus:DI (match_operand:DI 1 "register_operand" "r") | |
2982 | (match_operand:DI 2 "register_operand" "r")))] | |
2983 | "" | |
2984 | "sub %R1,%R2,%R0\;subb %1,%2,%0" | |
c47decad JL |
2985 | [(set_attr "type" "binary") |
2986 | (set_attr "length" "8")]) | |
c733e074 | 2987 | |
c733e074 TM |
2988 | (define_insn "subsi3" |
2989 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2990 | (minus:SI (match_operand:SI 1 "arith11_operand" "r,I") | |
2991 | (match_operand:SI 2 "register_operand" "r,r")))] | |
2992 | "" | |
2993 | "@ | |
2994 | sub %1,%2,%0 | |
c47decad JL |
2995 | subi %1,%2,%0" |
2996 | [(set_attr "type" "binary,binary") | |
2997 | (set_attr "length" "4,4")]) | |
c733e074 | 2998 | |
29ed7081 JL |
2999 | ;; Clobbering a "register_operand" instead of a match_scratch |
3000 | ;; in operand3 of millicode calls avoids spilling %r1 and | |
3001 | ;; produces better code. | |
c733e074 | 3002 | |
29ed7081 | 3003 | ;; The mulsi3 insns set up registers for the millicode call. |
c733e074 | 3004 | (define_expand "mulsi3" |
ac153498 TG |
3005 | [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) |
3006 | (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) | |
c733e074 | 3007 | (parallel [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25))) |
0b27d5dd | 3008 | (clobber (match_dup 3)) |
c733e074 TM |
3009 | (clobber (reg:SI 26)) |
3010 | (clobber (reg:SI 25)) | |
3011 | (clobber (reg:SI 31))]) | |
3012 | (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] | |
3013 | "" | |
d2a94ec0 TM |
3014 | " |
3015 | { | |
925cf581 | 3016 | if (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT) |
d2a94ec0 TM |
3017 | { |
3018 | rtx scratch = gen_reg_rtx (DImode); | |
dc4e989c TG |
3019 | operands[1] = force_reg (SImode, operands[1]); |
3020 | operands[2] = force_reg (SImode, operands[2]); | |
d2a94ec0 TM |
3021 | emit_insn (gen_umulsidi3 (scratch, operands[1], operands[2])); |
3022 | emit_insn (gen_rtx (SET, VOIDmode, | |
3023 | operands[0], | |
3024 | gen_rtx (SUBREG, SImode, scratch, 1))); | |
3025 | DONE; | |
3026 | } | |
0b27d5dd | 3027 | operands[3] = gen_reg_rtx (SImode); |
d2a94ec0 TM |
3028 | }") |
3029 | ||
3030 | (define_insn "umulsidi3" | |
0b27d5dd TG |
3031 | [(set (match_operand:DI 0 "nonimmediate_operand" "=f") |
3032 | (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f")) | |
3033 | (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "f"))))] | |
925cf581 | 3034 | "TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT" |
d2a94ec0 | 3035 | "xmpyu %1,%2,%0" |
c47decad JL |
3036 | [(set_attr "type" "fpmuldbl") |
3037 | (set_attr "length" "4")]) | |
c733e074 | 3038 | |
2f95ebc2 | 3039 | (define_insn "" |
0b27d5dd TG |
3040 | [(set (match_operand:DI 0 "nonimmediate_operand" "=f") |
3041 | (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f")) | |
3042 | (match_operand:DI 2 "uint32_operand" "f")))] | |
925cf581 | 3043 | "TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT" |
2f95ebc2 | 3044 | "xmpyu %1,%R2,%0" |
c47decad JL |
3045 | [(set_attr "type" "fpmuldbl") |
3046 | (set_attr "length" "4")]) | |
2f95ebc2 | 3047 | |
c733e074 TM |
3048 | (define_insn "" |
3049 | [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25))) | |
29ed7081 | 3050 | (clobber (match_operand:SI 0 "register_operand" "=a")) |
c733e074 TM |
3051 | (clobber (reg:SI 26)) |
3052 | (clobber (reg:SI 25)) | |
3053 | (clobber (reg:SI 31))] | |
3054 | "" | |
f854c12c | 3055 | "* return output_mul_insn (0, insn);" |
f726ea7d | 3056 | [(set_attr "type" "milli") |
279c9bde | 3057 | (set (attr "length") |
6a73009d JL |
3058 | (cond [ |
3059 | ;; Target (or stub) within reach | |
3060 | (and (lt (plus (symbol_ref "total_code_bytes") (pc)) | |
3061 | (const_int 240000)) | |
3062 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3063 | (const_int 0))) | |
3064 | (const_int 4) | |
3065 | ||
3066 | ;; NO_SPACE_REGS | |
3aba034b | 3067 | (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") |
6a73009d JL |
3068 | (const_int 0)) |
3069 | (const_int 8) | |
3070 | ||
3071 | ;; Out of reach, but not PIC or PORTABLE_RUNTIME | |
3072 | ;; same as NO_SPACE_REGS code | |
3073 | (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3074 | (const_int 0)) | |
3075 | (eq (symbol_ref "flag_pic") | |
3076 | (const_int 0))) | |
3077 | (const_int 8)] | |
3078 | ||
3079 | ;; Out of range and either PIC or PORTABLE_RUNTIME | |
3080 | (const_int 24)))]) | |
c733e074 TM |
3081 | |
3082 | ;;; Division and mod. | |
c733e074 | 3083 | (define_expand "divsi3" |
ac153498 TG |
3084 | [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) |
3085 | (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) | |
c733e074 | 3086 | (parallel [(set (reg:SI 29) (div:SI (reg:SI 26) (reg:SI 25))) |
b16656f6 | 3087 | (clobber (match_dup 3)) |
c733e074 TM |
3088 | (clobber (reg:SI 26)) |
3089 | (clobber (reg:SI 25)) | |
3090 | (clobber (reg:SI 31))]) | |
3091 | (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] | |
3092 | "" | |
3093 | " | |
3094 | { | |
c210e6ae TG |
3095 | operands[3] = gen_reg_rtx (SImode); |
3096 | if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 0)) | |
3097 | DONE; | |
c733e074 TM |
3098 | }") |
3099 | ||
3100 | (define_insn "" | |
3101 | [(set (reg:SI 29) | |
c210e6ae | 3102 | (div:SI (reg:SI 26) (match_operand:SI 0 "div_operand" ""))) |
29ed7081 | 3103 | (clobber (match_operand:SI 1 "register_operand" "=a")) |
c733e074 TM |
3104 | (clobber (reg:SI 26)) |
3105 | (clobber (reg:SI 25)) | |
3106 | (clobber (reg:SI 31))] | |
2f95ebc2 TG |
3107 | "" |
3108 | "* | |
3109 | return output_div_insn (operands, 0, insn);" | |
f726ea7d | 3110 | [(set_attr "type" "milli") |
279c9bde | 3111 | (set (attr "length") |
6a73009d JL |
3112 | (cond [ |
3113 | ;; Target (or stub) within reach | |
3114 | (and (lt (plus (symbol_ref "total_code_bytes") (pc)) | |
3115 | (const_int 240000)) | |
3116 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3117 | (const_int 0))) | |
3118 | (const_int 4) | |
3119 | ||
3120 | ;; NO_SPACE_REGS | |
3aba034b | 3121 | (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") |
6a73009d JL |
3122 | (const_int 0)) |
3123 | (const_int 8) | |
3124 | ||
3125 | ;; Out of reach, but not PIC or PORTABLE_RUNTIME | |
3126 | ;; same as NO_SPACE_REGS code | |
3127 | (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3128 | (const_int 0)) | |
3129 | (eq (symbol_ref "flag_pic") | |
3130 | (const_int 0))) | |
3131 | (const_int 8)] | |
3132 | ||
3133 | ;; Out of range and either PIC or PORTABLE_RUNTIME | |
3134 | (const_int 24)))]) | |
c733e074 TM |
3135 | |
3136 | (define_expand "udivsi3" | |
ac153498 TG |
3137 | [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) |
3138 | (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) | |
c733e074 | 3139 | (parallel [(set (reg:SI 29) (udiv:SI (reg:SI 26) (reg:SI 25))) |
b16656f6 | 3140 | (clobber (match_dup 3)) |
c733e074 TM |
3141 | (clobber (reg:SI 26)) |
3142 | (clobber (reg:SI 25)) | |
3143 | (clobber (reg:SI 31))]) | |
3144 | (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] | |
3145 | "" | |
3146 | " | |
3147 | { | |
c210e6ae TG |
3148 | operands[3] = gen_reg_rtx (SImode); |
3149 | if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 1)) | |
3150 | DONE; | |
c733e074 TM |
3151 | }") |
3152 | ||
3153 | (define_insn "" | |
3154 | [(set (reg:SI 29) | |
c210e6ae | 3155 | (udiv:SI (reg:SI 26) (match_operand:SI 0 "div_operand" ""))) |
29ed7081 | 3156 | (clobber (match_operand:SI 1 "register_operand" "=a")) |
c733e074 TM |
3157 | (clobber (reg:SI 26)) |
3158 | (clobber (reg:SI 25)) | |
3159 | (clobber (reg:SI 31))] | |
2f95ebc2 TG |
3160 | "" |
3161 | "* | |
3162 | return output_div_insn (operands, 1, insn);" | |
f726ea7d | 3163 | [(set_attr "type" "milli") |
279c9bde | 3164 | (set (attr "length") |
6a73009d JL |
3165 | (cond [ |
3166 | ;; Target (or stub) within reach | |
3167 | (and (lt (plus (symbol_ref "total_code_bytes") (pc)) | |
3168 | (const_int 240000)) | |
3169 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3170 | (const_int 0))) | |
3171 | (const_int 4) | |
3172 | ||
3173 | ;; NO_SPACE_REGS | |
3aba034b | 3174 | (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") |
6a73009d JL |
3175 | (const_int 0)) |
3176 | (const_int 8) | |
3177 | ||
3178 | ;; Out of reach, but not PIC or PORTABLE_RUNTIME | |
3179 | ;; same as NO_SPACE_REGS code | |
3180 | (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3181 | (const_int 0)) | |
3182 | (eq (symbol_ref "flag_pic") | |
3183 | (const_int 0))) | |
3184 | (const_int 8)] | |
3185 | ||
3186 | ;; Out of range and either PIC or PORTABLE_RUNTIME | |
3187 | (const_int 24)))]) | |
c733e074 TM |
3188 | |
3189 | (define_expand "modsi3" | |
ac153498 TG |
3190 | [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) |
3191 | (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) | |
c733e074 | 3192 | (parallel [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25))) |
b16656f6 | 3193 | (clobber (match_dup 3)) |
c733e074 TM |
3194 | (clobber (reg:SI 26)) |
3195 | (clobber (reg:SI 25)) | |
3196 | (clobber (reg:SI 31))]) | |
3197 | (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] | |
3198 | "" | |
3199 | " | |
3200 | { | |
c210e6ae | 3201 | operands[3] = gen_reg_rtx (SImode); |
c733e074 | 3202 | }") |
876662ef | 3203 | |
c733e074 TM |
3204 | (define_insn "" |
3205 | [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25))) | |
29ed7081 | 3206 | (clobber (match_operand:SI 0 "register_operand" "=a")) |
c733e074 TM |
3207 | (clobber (reg:SI 26)) |
3208 | (clobber (reg:SI 25)) | |
3209 | (clobber (reg:SI 31))] | |
3210 | "" | |
3211 | "* | |
f854c12c | 3212 | return output_mod_insn (0, insn);" |
f726ea7d | 3213 | [(set_attr "type" "milli") |
279c9bde | 3214 | (set (attr "length") |
6a73009d JL |
3215 | (cond [ |
3216 | ;; Target (or stub) within reach | |
3217 | (and (lt (plus (symbol_ref "total_code_bytes") (pc)) | |
3218 | (const_int 240000)) | |
3219 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3220 | (const_int 0))) | |
3221 | (const_int 4) | |
3222 | ||
3223 | ;; NO_SPACE_REGS | |
3aba034b | 3224 | (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") |
6a73009d JL |
3225 | (const_int 0)) |
3226 | (const_int 8) | |
3227 | ||
3228 | ;; Out of reach, but not PIC or PORTABLE_RUNTIME | |
3229 | ;; same as NO_SPACE_REGS code | |
3230 | (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3231 | (const_int 0)) | |
3232 | (eq (symbol_ref "flag_pic") | |
3233 | (const_int 0))) | |
3234 | (const_int 8)] | |
3235 | ||
3236 | ;; Out of range and either PIC or PORTABLE_RUNTIME | |
3237 | (const_int 24)))]) | |
c733e074 TM |
3238 | |
3239 | (define_expand "umodsi3" | |
ac153498 TG |
3240 | [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) |
3241 | (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) | |
c733e074 | 3242 | (parallel [(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25))) |
b16656f6 | 3243 | (clobber (match_dup 3)) |
c733e074 TM |
3244 | (clobber (reg:SI 26)) |
3245 | (clobber (reg:SI 25)) | |
3246 | (clobber (reg:SI 31))]) | |
3247 | (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] | |
3248 | "" | |
3249 | " | |
3250 | { | |
c210e6ae | 3251 | operands[3] = gen_reg_rtx (SImode); |
c733e074 TM |
3252 | }") |
3253 | ||
3254 | (define_insn "" | |
3255 | [(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25))) | |
29ed7081 | 3256 | (clobber (match_operand:SI 0 "register_operand" "=a")) |
c733e074 TM |
3257 | (clobber (reg:SI 26)) |
3258 | (clobber (reg:SI 25)) | |
3259 | (clobber (reg:SI 31))] | |
3260 | "" | |
3261 | "* | |
f854c12c | 3262 | return output_mod_insn (1, insn);" |
f726ea7d | 3263 | [(set_attr "type" "milli") |
279c9bde | 3264 | (set (attr "length") |
6a73009d JL |
3265 | (cond [ |
3266 | ;; Target (or stub) within reach | |
3267 | (and (lt (plus (symbol_ref "total_code_bytes") (pc)) | |
3268 | (const_int 240000)) | |
3269 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3270 | (const_int 0))) | |
3271 | (const_int 4) | |
3272 | ||
3273 | ;; NO_SPACE_REGS | |
3aba034b | 3274 | (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") |
6a73009d JL |
3275 | (const_int 0)) |
3276 | (const_int 8) | |
3277 | ||
3278 | ;; Out of reach, but not PIC or PORTABLE_RUNTIME | |
3279 | ;; same as NO_SPACE_REGS code | |
3280 | (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
3281 | (const_int 0)) | |
3282 | (eq (symbol_ref "flag_pic") | |
3283 | (const_int 0))) | |
3284 | (const_int 8)] | |
3285 | ||
3286 | ;; Out of range and either PIC or PORTABLE_RUNTIME | |
3287 | (const_int 24)))]) | |
c733e074 TM |
3288 | |
3289 | ;;- and instructions | |
3290 | ;; We define DImode `and` so with DImode `not` we can get | |
3291 | ;; DImode `andn`. Other combinations are possible. | |
3292 | ||
3293 | (define_expand "anddi3" | |
3294 | [(set (match_operand:DI 0 "register_operand" "") | |
3295 | (and:DI (match_operand:DI 1 "arith_double_operand" "") | |
3296 | (match_operand:DI 2 "arith_double_operand" "")))] | |
3297 | "" | |
3298 | " | |
3299 | { | |
3300 | if (! register_operand (operands[1], DImode) | |
3301 | || ! register_operand (operands[2], DImode)) | |
3302 | /* Let GCC break this into word-at-a-time operations. */ | |
3303 | FAIL; | |
3304 | }") | |
3305 | ||
3306 | (define_insn "" | |
3307 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3308 | (and:DI (match_operand:DI 1 "register_operand" "%r") | |
3309 | (match_operand:DI 2 "register_operand" "r")))] | |
3310 | "" | |
3311 | "and %1,%2,%0\;and %R1,%R2,%R0" | |
c47decad JL |
3312 | [(set_attr "type" "binary") |
3313 | (set_attr "length" "8")]) | |
c733e074 | 3314 | |
dadae817 | 3315 | ; The ? for op1 makes reload prefer zdepi instead of loading a huge |
2f95ebc2 | 3316 | ; constant with ldil;ldo. |
c733e074 | 3317 | (define_insn "andsi3" |
876662ef | 3318 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
dadae817 | 3319 | (and:SI (match_operand:SI 1 "register_operand" "%?r,0") |
876662ef | 3320 | (match_operand:SI 2 "and_operand" "rO,P")))] |
c733e074 | 3321 | "" |
34f921d8 | 3322 | "* return output_and (operands); " |
c47decad JL |
3323 | [(set_attr "type" "binary,shift") |
3324 | (set_attr "length" "4,4")]) | |
c733e074 TM |
3325 | |
3326 | (define_insn "" | |
3327 | [(set (match_operand:DI 0 "register_operand" "=r") | |
876662ef TG |
3328 | (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) |
3329 | (match_operand:DI 2 "register_operand" "r")))] | |
c733e074 TM |
3330 | "" |
3331 | "andcm %2,%1,%0\;andcm %R2,%R1,%R0" | |
c47decad JL |
3332 | [(set_attr "type" "binary") |
3333 | (set_attr "length" "8")]) | |
c733e074 TM |
3334 | |
3335 | (define_insn "" | |
3336 | [(set (match_operand:SI 0 "register_operand" "=r") | |
876662ef TG |
3337 | (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) |
3338 | (match_operand:SI 2 "register_operand" "r")))] | |
c733e074 | 3339 | "" |
c47decad JL |
3340 | "andcm %2,%1,%0" |
3341 | [(set_attr "type" "binary") | |
3342 | (set_attr "length" "4")]) | |
c733e074 TM |
3343 | |
3344 | (define_expand "iordi3" | |
3345 | [(set (match_operand:DI 0 "register_operand" "") | |
3346 | (ior:DI (match_operand:DI 1 "arith_double_operand" "") | |
3347 | (match_operand:DI 2 "arith_double_operand" "")))] | |
3348 | "" | |
3349 | " | |
3350 | { | |
3351 | if (! register_operand (operands[1], DImode) | |
3352 | || ! register_operand (operands[2], DImode)) | |
3353 | /* Let GCC break this into word-at-a-time operations. */ | |
3354 | FAIL; | |
3355 | }") | |
3356 | ||
3357 | (define_insn "" | |
3358 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3359 | (ior:DI (match_operand:DI 1 "register_operand" "%r") | |
3360 | (match_operand:DI 2 "register_operand" "r")))] | |
3361 | "" | |
3362 | "or %1,%2,%0\;or %R1,%R2,%R0" | |
c47decad JL |
3363 | [(set_attr "type" "binary") |
3364 | (set_attr "length" "8")]) | |
c733e074 | 3365 | |
d5db6922 TG |
3366 | ;; Need a define_expand because we've run out of CONST_OK... characters. |
3367 | (define_expand "iorsi3" | |
3368 | [(set (match_operand:SI 0 "register_operand" "") | |
3369 | (ior:SI (match_operand:SI 1 "register_operand" "") | |
3370 | (match_operand:SI 2 "arith32_operand" "")))] | |
3371 | "" | |
3372 | " | |
3373 | { | |
3374 | if (! (ior_operand (operands[2]) || register_operand (operands[2]))) | |
3375 | operands[2] = force_reg (SImode, operands[2]); | |
3376 | }") | |
3377 | ||
9a82d0bb | 3378 | (define_insn "" |
c47decad JL |
3379 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
3380 | (ior:SI (match_operand:SI 1 "register_operand" "0,0") | |
3381 | (match_operand:SI 2 "ior_operand" "M,i")))] | |
9a82d0bb | 3382 | "" |
34f921d8 | 3383 | "* return output_ior (operands); " |
c47decad JL |
3384 | [(set_attr "type" "binary,shift") |
3385 | (set_attr "length" "4,4")]) | |
9a82d0bb | 3386 | |
d5db6922 | 3387 | (define_insn "" |
9a82d0bb JL |
3388 | [(set (match_operand:SI 0 "register_operand" "=r") |
3389 | (ior:SI (match_operand:SI 1 "register_operand" "%r") | |
3390 | (match_operand:SI 2 "register_operand" "r")))] | |
c733e074 | 3391 | "" |
c47decad JL |
3392 | "or %1,%2,%0" |
3393 | [(set_attr "type" "binary") | |
3394 | (set_attr "length" "4")]) | |
c733e074 TM |
3395 | |
3396 | (define_expand "xordi3" | |
3397 | [(set (match_operand:DI 0 "register_operand" "") | |
3398 | (xor:DI (match_operand:DI 1 "arith_double_operand" "") | |
3399 | (match_operand:DI 2 "arith_double_operand" "")))] | |
3400 | "" | |
3401 | " | |
3402 | { | |
3403 | if (! register_operand (operands[1], DImode) | |
3404 | || ! register_operand (operands[2], DImode)) | |
3405 | /* Let GCC break this into word-at-a-time operations. */ | |
3406 | FAIL; | |
3407 | }") | |
3408 | ||
3409 | (define_insn "" | |
3410 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3411 | (xor:DI (match_operand:DI 1 "register_operand" "%r") | |
3412 | (match_operand:DI 2 "register_operand" "r")))] | |
3413 | "" | |
3414 | "xor %1,%2,%0\;xor %R1,%R2,%R0" | |
c47decad JL |
3415 | [(set_attr "type" "binary") |
3416 | (set_attr "length" "8")]) | |
c733e074 TM |
3417 | |
3418 | (define_insn "xorsi3" | |
3419 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3420 | (xor:SI (match_operand:SI 1 "register_operand" "%r") | |
3421 | (match_operand:SI 2 "register_operand" "r")))] | |
3422 | "" | |
c47decad JL |
3423 | "xor %1,%2,%0" |
3424 | [(set_attr "type" "binary") | |
3425 | (set_attr "length" "4")]) | |
c733e074 TM |
3426 | |
3427 | (define_insn "negdi2" | |
3428 | [(set (match_operand:DI 0 "register_operand" "=r") | |
3429 | (neg:DI (match_operand:DI 1 "register_operand" "r")))] | |
3430 | "" | |
3431 | "sub 0,%R1,%R0\;subb 0,%1,%0" | |
3432 | [(set_attr "type" "unary") | |
4c2164b7 | 3433 | (set_attr "length" "8")]) |
c733e074 TM |
3434 | |
3435 | (define_insn "negsi2" | |
3436 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3437 | (neg:SI (match_operand:SI 1 "register_operand" "r")))] | |
3438 | "" | |
876662ef | 3439 | "sub 0,%1,%0" |
c47decad JL |
3440 | [(set_attr "type" "unary") |
3441 | (set_attr "length" "4")]) | |
c733e074 TM |
3442 | |
3443 | (define_expand "one_cmpldi2" | |
3444 | [(set (match_operand:DI 0 "register_operand" "") | |
3445 | (not:DI (match_operand:DI 1 "arith_double_operand" "")))] | |
3446 | "" | |
3447 | " | |
3448 | { | |
3449 | if (! register_operand (operands[1], DImode)) | |
3450 | FAIL; | |
3451 | }") | |
3452 | ||
3453 | (define_insn "" | |
3454 | [(set (match_operand:DI 0 "register_operand" "=r") | |
876662ef | 3455 | (not:DI (match_operand:DI 1 "register_operand" "r")))] |
c733e074 TM |
3456 | "" |
3457 | "uaddcm 0,%1,%0\;uaddcm 0,%R1,%R0" | |
3458 | [(set_attr "type" "unary") | |
4c2164b7 | 3459 | (set_attr "length" "8")]) |
c733e074 TM |
3460 | |
3461 | (define_insn "one_cmplsi2" | |
3462 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3463 | (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
3464 | "" | |
3465 | "uaddcm 0,%1,%0" | |
c47decad JL |
3466 | [(set_attr "type" "unary") |
3467 | (set_attr "length" "4")]) | |
c733e074 TM |
3468 | \f |
3469 | ;; Floating point arithmetic instructions. | |
3470 | ||
3471 | (define_insn "adddf3" | |
0b27d5dd TG |
3472 | [(set (match_operand:DF 0 "register_operand" "=f") |
3473 | (plus:DF (match_operand:DF 1 "register_operand" "f") | |
3474 | (match_operand:DF 2 "register_operand" "f")))] | |
925cf581 | 3475 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3476 | "fadd,dbl %1,%2,%0" |
c47decad | 3477 | [(set_attr "type" "fpalu") |
c4bb6b38 | 3478 | (set_attr "pa_combine_type" "faddsub") |
c47decad | 3479 | (set_attr "length" "4")]) |
c733e074 TM |
3480 | |
3481 | (define_insn "addsf3" | |
0b27d5dd TG |
3482 | [(set (match_operand:SF 0 "register_operand" "=f") |
3483 | (plus:SF (match_operand:SF 1 "register_operand" "f") | |
3484 | (match_operand:SF 2 "register_operand" "f")))] | |
925cf581 | 3485 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3486 | "fadd,sgl %1,%2,%0" |
c47decad | 3487 | [(set_attr "type" "fpalu") |
c4bb6b38 | 3488 | (set_attr "pa_combine_type" "faddsub") |
c47decad | 3489 | (set_attr "length" "4")]) |
c733e074 TM |
3490 | |
3491 | (define_insn "subdf3" | |
0b27d5dd TG |
3492 | [(set (match_operand:DF 0 "register_operand" "=f") |
3493 | (minus:DF (match_operand:DF 1 "register_operand" "f") | |
3494 | (match_operand:DF 2 "register_operand" "f")))] | |
925cf581 | 3495 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3496 | "fsub,dbl %1,%2,%0" |
c47decad | 3497 | [(set_attr "type" "fpalu") |
c4bb6b38 | 3498 | (set_attr "pa_combine_type" "faddsub") |
c47decad | 3499 | (set_attr "length" "4")]) |
c733e074 TM |
3500 | |
3501 | (define_insn "subsf3" | |
0b27d5dd TG |
3502 | [(set (match_operand:SF 0 "register_operand" "=f") |
3503 | (minus:SF (match_operand:SF 1 "register_operand" "f") | |
3504 | (match_operand:SF 2 "register_operand" "f")))] | |
925cf581 | 3505 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3506 | "fsub,sgl %1,%2,%0" |
c47decad | 3507 | [(set_attr "type" "fpalu") |
c4bb6b38 | 3508 | (set_attr "pa_combine_type" "faddsub") |
c47decad | 3509 | (set_attr "length" "4")]) |
c733e074 TM |
3510 | |
3511 | (define_insn "muldf3" | |
0b27d5dd TG |
3512 | [(set (match_operand:DF 0 "register_operand" "=f") |
3513 | (mult:DF (match_operand:DF 1 "register_operand" "f") | |
3514 | (match_operand:DF 2 "register_operand" "f")))] | |
925cf581 | 3515 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3516 | "fmpy,dbl %1,%2,%0" |
c47decad | 3517 | [(set_attr "type" "fpmuldbl") |
c4bb6b38 | 3518 | (set_attr "pa_combine_type" "fmpy") |
c47decad | 3519 | (set_attr "length" "4")]) |
c733e074 TM |
3520 | |
3521 | (define_insn "mulsf3" | |
0b27d5dd TG |
3522 | [(set (match_operand:SF 0 "register_operand" "=f") |
3523 | (mult:SF (match_operand:SF 1 "register_operand" "f") | |
3524 | (match_operand:SF 2 "register_operand" "f")))] | |
925cf581 | 3525 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3526 | "fmpy,sgl %1,%2,%0" |
c47decad | 3527 | [(set_attr "type" "fpmulsgl") |
c4bb6b38 | 3528 | (set_attr "pa_combine_type" "fmpy") |
c47decad | 3529 | (set_attr "length" "4")]) |
c733e074 TM |
3530 | |
3531 | (define_insn "divdf3" | |
0b27d5dd TG |
3532 | [(set (match_operand:DF 0 "register_operand" "=f") |
3533 | (div:DF (match_operand:DF 1 "register_operand" "f") | |
3534 | (match_operand:DF 2 "register_operand" "f")))] | |
925cf581 | 3535 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3536 | "fdiv,dbl %1,%2,%0" |
c47decad JL |
3537 | [(set_attr "type" "fpdivdbl") |
3538 | (set_attr "length" "4")]) | |
c733e074 TM |
3539 | |
3540 | (define_insn "divsf3" | |
0b27d5dd TG |
3541 | [(set (match_operand:SF 0 "register_operand" "=f") |
3542 | (div:SF (match_operand:SF 1 "register_operand" "f") | |
3543 | (match_operand:SF 2 "register_operand" "f")))] | |
925cf581 | 3544 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3545 | "fdiv,sgl %1,%2,%0" |
c47decad JL |
3546 | [(set_attr "type" "fpdivsgl") |
3547 | (set_attr "length" "4")]) | |
c733e074 TM |
3548 | |
3549 | (define_insn "negdf2" | |
0b27d5dd TG |
3550 | [(set (match_operand:DF 0 "register_operand" "=f") |
3551 | (neg:DF (match_operand:DF 1 "register_operand" "f")))] | |
925cf581 | 3552 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3553 | "fsub,dbl 0,%1,%0" |
c47decad JL |
3554 | [(set_attr "type" "fpalu") |
3555 | (set_attr "length" "4")]) | |
c733e074 TM |
3556 | |
3557 | (define_insn "negsf2" | |
0b27d5dd TG |
3558 | [(set (match_operand:SF 0 "register_operand" "=f") |
3559 | (neg:SF (match_operand:SF 1 "register_operand" "f")))] | |
925cf581 | 3560 | "! TARGET_SOFT_FLOAT" |
ac153498 | 3561 | "fsub,sgl 0,%1,%0" |
c47decad JL |
3562 | [(set_attr "type" "fpalu") |
3563 | (set_attr "length" "4")]) | |
c733e074 TM |
3564 | |
3565 | (define_insn "absdf2" | |
0b27d5dd TG |
3566 | [(set (match_operand:DF 0 "register_operand" "=f") |
3567 | (abs:DF (match_operand:DF 1 "register_operand" "f")))] | |
925cf581 | 3568 | "! TARGET_SOFT_FLOAT" |
cb432e02 | 3569 | "fabs,dbl %1,%0" |
c47decad JL |
3570 | [(set_attr "type" "fpalu") |
3571 | (set_attr "length" "4")]) | |
c733e074 TM |
3572 | |
3573 | (define_insn "abssf2" | |
0b27d5dd TG |
3574 | [(set (match_operand:SF 0 "register_operand" "=f") |
3575 | (abs:SF (match_operand:SF 1 "register_operand" "f")))] | |
925cf581 | 3576 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3577 | "fabs,sgl %1,%0" |
c47decad JL |
3578 | [(set_attr "type" "fpalu") |
3579 | (set_attr "length" "4")]) | |
c733e074 TM |
3580 | |
3581 | (define_insn "sqrtdf2" | |
0b27d5dd TG |
3582 | [(set (match_operand:DF 0 "register_operand" "=f") |
3583 | (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] | |
925cf581 | 3584 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3585 | "fsqrt,dbl %1,%0" |
c47decad JL |
3586 | [(set_attr "type" "fpsqrtdbl") |
3587 | (set_attr "length" "4")]) | |
c733e074 TM |
3588 | |
3589 | (define_insn "sqrtsf2" | |
0b27d5dd TG |
3590 | [(set (match_operand:SF 0 "register_operand" "=f") |
3591 | (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] | |
925cf581 | 3592 | "! TARGET_SOFT_FLOAT" |
c733e074 | 3593 | "fsqrt,sgl %1,%0" |
c47decad JL |
3594 | [(set_attr "type" "fpsqrtsgl") |
3595 | (set_attr "length" "4")]) | |
c733e074 TM |
3596 | \f |
3597 | ;;- Shift instructions | |
3598 | ||
3599 | ;; Optimized special case of shifting. | |
3600 | ||
3601 | (define_insn "" | |
3602 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3603 | (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") | |
3604 | (const_int 24)))] | |
3605 | "" | |
907f67cc TG |
3606 | "ldb%M1 %1,%0" |
3607 | [(set_attr "type" "load") | |
4c2164b7 | 3608 | (set_attr "length" "4")]) |
907f67cc TG |
3609 | |
3610 | (define_insn "" | |
3611 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3612 | (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") | |
3613 | (const_int 16)))] | |
3614 | "" | |
3615 | "ldh%M1 %1,%0" | |
3616 | [(set_attr "type" "load") | |
4c2164b7 | 3617 | (set_attr "length" "4")]) |
c733e074 TM |
3618 | |
3619 | (define_insn "" | |
3620 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3621 | (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r") | |
b8be8876 | 3622 | (match_operand:SI 3 "shadd_operand" "")) |
81722625 | 3623 | (match_operand:SI 1 "register_operand" "r")))] |
c733e074 | 3624 | "" |
c47decad JL |
3625 | "sh%O3addl %2,%1,%0" |
3626 | [(set_attr "type" "binary") | |
3627 | (set_attr "length" "4")]) | |
c733e074 | 3628 | |
b8be8876 | 3629 | ;; This variant of the above insn can occur if the first operand |
81722625 | 3630 | ;; is the frame pointer. This is a kludge, but there doesn't |
6358b911 | 3631 | ;; seem to be a way around it. Only recognize it while reloading. |
3f935c0b JL |
3632 | ;; Note how operand 3 uses a predicate of "const_int_operand", but |
3633 | ;; has constraints allowing a register. I don't know how this works, | |
3634 | ;; but it somehow makes sure that out-of-range constants are placed | |
3635 | ;; in a register which somehow magically is a "const_int_operand". | |
3636 | ;; (this was stolen from alpha.md, I'm not going to try and change it. | |
81722625 JL |
3637 | |
3638 | (define_insn "" | |
b16656f6 TG |
3639 | [(set (match_operand:SI 0 "register_operand" "=&r,r") |
3640 | (plus:SI (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r,r") | |
b8be8876 | 3641 | (match_operand:SI 4 "shadd_operand" "")) |
b16656f6 TG |
3642 | (match_operand:SI 1 "register_operand" "r,r")) |
3643 | (match_operand:SI 3 "const_int_operand" "r,J")))] | |
81722625 | 3644 | "reload_in_progress" |
b16656f6 TG |
3645 | "@ |
3646 | sh%O4addl %2,%1,%0\;addl %3,%0,%0 | |
3647 | sh%O4addl %2,%1,%0\;ldo %3(%0),%0" | |
81722625 | 3648 | [(set_attr "type" "multi") |
4c2164b7 | 3649 | (set_attr "length" "8")]) |
81722625 | 3650 | |
c733e074 TM |
3651 | (define_expand "ashlsi3" |
3652 | [(set (match_operand:SI 0 "register_operand" "") | |
95246213 | 3653 | (ashift:SI (match_operand:SI 1 "lhs_lshift_operand" "") |
ba0443bb | 3654 | (match_operand:SI 2 "arith32_operand" "")))] |
c733e074 TM |
3655 | "" |
3656 | " | |
3657 | { | |
3658 | if (GET_CODE (operands[2]) != CONST_INT) | |
3659 | { | |
3660 | rtx temp = gen_reg_rtx (SImode); | |
6f672dc0 | 3661 | emit_insn (gen_subsi3 (temp, GEN_INT (31), operands[2])); |
c210e6ae TG |
3662 | if (GET_CODE (operands[1]) == CONST_INT) |
3663 | emit_insn (gen_zvdep_imm (operands[0], operands[1], temp)); | |
3664 | else | |
3665 | emit_insn (gen_zvdep32 (operands[0], operands[1], temp)); | |
c733e074 TM |
3666 | DONE; |
3667 | } | |
2f95ebc2 | 3668 | /* Make sure both inputs are not constants, |
c210e6ae | 3669 | there are no patterns for that. */ |
56a65d12 | 3670 | operands[1] = force_reg (SImode, operands[1]); |
c733e074 TM |
3671 | }") |
3672 | ||
3673 | (define_insn "" | |
56a65d12 TG |
3674 | [(set (match_operand:SI 0 "register_operand" "=r") |
3675 | (ashift:SI (match_operand:SI 1 "register_operand" "r") | |
3676 | (match_operand:SI 2 "const_int_operand" "n")))] | |
3677 | "" | |
34f921d8 | 3678 | "zdep %1,%P2,%L2,%0" |
c47decad | 3679 | [(set_attr "type" "shift") |
4c2164b7 | 3680 | (set_attr "length" "4")]) |
c733e074 | 3681 | |
95246213 TG |
3682 | ; Match cases of op1 a CONST_INT here that zvdep_imm doesn't handle. |
3683 | ; Doing it like this makes slightly better code since reload can | |
3684 | ; replace a register with a known value in range -16..15 with a | |
3685 | ; constant. Ideally, we would like to merge zvdep32 and zvdep_imm, | |
3686 | ; but since we have no more CONST_OK... characters, that is not | |
3687 | ; possible. | |
cb524f44 | 3688 | (define_insn "zvdep32" |
56a65d12 TG |
3689 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
3690 | (ashift:SI (match_operand:SI 1 "arith5_operand" "r,L") | |
3691 | (minus:SI (const_int 31) | |
3692 | (match_operand:SI 2 "register_operand" "q,q"))))] | |
3693 | "" | |
3694 | "@ | |
3695 | zvdep %1,32,%0 | |
c47decad JL |
3696 | zvdepi %1,32,%0" |
3697 | [(set_attr "type" "shift,shift") | |
3698 | (set_attr "length" "4,4")]) | |
c733e074 | 3699 | |
95246213 TG |
3700 | (define_insn "zvdep_imm" |
3701 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3702 | (ashift:SI (match_operand:SI 1 "lhs_lshift_cint_operand" "") | |
3703 | (minus:SI (const_int 31) | |
3704 | (match_operand:SI 2 "register_operand" "q"))))] | |
3705 | "" | |
3706 | "* | |
3707 | { | |
3708 | int x = INTVAL (operands[1]); | |
3709 | operands[2] = GEN_INT (4 + exact_log2 ((x >> 4) + 1)); | |
3710 | operands[1] = GEN_INT ((x & 0xf) - 0x10); | |
3711 | return \"zvdepi %1,%2,%0\"; | |
c47decad JL |
3712 | }" |
3713 | [(set_attr "type" "shift") | |
3714 | (set_attr "length" "4")]) | |
95246213 | 3715 | |
2f95ebc2 TG |
3716 | (define_insn "vdepi_ior" |
3717 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3718 | (ior:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "") | |
3719 | (minus:SI (const_int 31) | |
3720 | (match_operand:SI 2 "register_operand" "q"))) | |
3721 | (match_operand:SI 3 "register_operand" "0")))] | |
3722 | ; accept ...0001...1, can this be generalized? | |
3723 | "exact_log2 (INTVAL (operands[1]) + 1) >= 0" | |
3724 | "* | |
3725 | { | |
3726 | int x = INTVAL (operands[1]); | |
3727 | operands[2] = GEN_INT (exact_log2 (x + 1)); | |
3728 | return \"vdepi -1,%2,%0\"; | |
c47decad JL |
3729 | }" |
3730 | [(set_attr "type" "shift") | |
3731 | (set_attr "length" "4")]) | |
2f95ebc2 TG |
3732 | |
3733 | (define_insn "vdepi_and" | |
3734 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3735 | (and:SI (rotate:SI (match_operand:SI 1 "const_int_operand" "") | |
3736 | (minus:SI (const_int 31) | |
3737 | (match_operand:SI 2 "register_operand" "q"))) | |
3738 | (match_operand:SI 3 "register_operand" "0")))] | |
3739 | ; this can be generalized...! | |
3740 | "INTVAL (operands[1]) == -2" | |
3741 | "* | |
3742 | { | |
3743 | int x = INTVAL (operands[1]); | |
3744 | operands[2] = GEN_INT (exact_log2 ((~x) + 1)); | |
3745 | return \"vdepi 0,%2,%0\"; | |
c47decad JL |
3746 | }" |
3747 | [(set_attr "type" "shift") | |
3748 | (set_attr "length" "4")]) | |
2f95ebc2 | 3749 | |
c733e074 TM |
3750 | (define_expand "ashrsi3" |
3751 | [(set (match_operand:SI 0 "register_operand" "") | |
3752 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "") | |
ba0443bb | 3753 | (match_operand:SI 2 "arith32_operand" "")))] |
c733e074 TM |
3754 | "" |
3755 | " | |
3756 | { | |
3757 | if (GET_CODE (operands[2]) != CONST_INT) | |
3758 | { | |
3759 | rtx temp = gen_reg_rtx (SImode); | |
6f672dc0 | 3760 | emit_insn (gen_subsi3 (temp, GEN_INT (31), operands[2])); |
cb524f44 | 3761 | emit_insn (gen_vextrs32 (operands[0], operands[1], temp)); |
c733e074 TM |
3762 | DONE; |
3763 | } | |
3764 | }") | |
3765 | ||
3766 | (define_insn "" | |
56a65d12 TG |
3767 | [(set (match_operand:SI 0 "register_operand" "=r") |
3768 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") | |
3769 | (match_operand:SI 2 "const_int_operand" "n")))] | |
3770 | "" | |
34f921d8 | 3771 | "extrs %1,%P2,%L2,%0" |
c47decad | 3772 | [(set_attr "type" "shift") |
4c2164b7 | 3773 | (set_attr "length" "4")]) |
c733e074 | 3774 | |
cb524f44 | 3775 | (define_insn "vextrs32" |
56a65d12 TG |
3776 | [(set (match_operand:SI 0 "register_operand" "=r") |
3777 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") | |
3778 | (minus:SI (const_int 31) | |
3779 | (match_operand:SI 2 "register_operand" "q"))))] | |
3780 | "" | |
c47decad JL |
3781 | "vextrs %1,32,%0" |
3782 | [(set_attr "type" "shift") | |
3783 | (set_attr "length" "4")]) | |
c733e074 | 3784 | |
cb524f44 | 3785 | (define_insn "lshrsi3" |
95246213 TG |
3786 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
3787 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") | |
3788 | (match_operand:SI 2 "arith32_operand" "q,n")))] | |
c733e074 | 3789 | "" |
95246213 TG |
3790 | "@ |
3791 | vshd 0,%1,%0 | |
34f921d8 | 3792 | extru %1,%P2,%L2,%0" |
c47decad | 3793 | [(set_attr "type" "shift") |
4c2164b7 | 3794 | (set_attr "length" "4")]) |
c733e074 | 3795 | |
cb524f44 | 3796 | (define_insn "rotrsi3" |
95246213 TG |
3797 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
3798 | (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") | |
3799 | (match_operand:SI 2 "arith32_operand" "q,n")))] | |
cb524f44 TG |
3800 | "" |
3801 | "* | |
c733e074 | 3802 | { |
cb524f44 | 3803 | if (GET_CODE (operands[2]) == CONST_INT) |
95246213 TG |
3804 | { |
3805 | operands[2] = GEN_INT (INTVAL (operands[2]) & 31); | |
3806 | return \"shd %1,%1,%2,%0\"; | |
3807 | } | |
cb524f44 TG |
3808 | else |
3809 | return \"vshd %1,%1,%0\"; | |
34f921d8 | 3810 | }" |
c47decad | 3811 | [(set_attr "type" "shift") |
4c2164b7 | 3812 | (set_attr "length" "4")]) |
cb524f44 | 3813 | |
c733e074 | 3814 | (define_insn "" |
cb524f44 TG |
3815 | [(set (match_operand:SI 0 "register_operand" "=r") |
3816 | (match_operator:SI 5 "plus_xor_ior_operator" | |
3817 | [(ashift:SI (match_operand:SI 1 "register_operand" "r") | |
3818 | (match_operand:SI 3 "const_int_operand" "n")) | |
3819 | (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") | |
3820 | (match_operand:SI 4 "const_int_operand" "n"))]))] | |
3821 | "INTVAL (operands[3]) + INTVAL (operands[4]) == 32" | |
3822 | "shd %1,%2,%4,%0" | |
c47decad | 3823 | [(set_attr "type" "shift") |
4c2164b7 | 3824 | (set_attr "length" "4")]) |
cb524f44 TG |
3825 | |
3826 | (define_insn "" | |
3827 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3828 | (match_operator:SI 5 "plus_xor_ior_operator" | |
3829 | [(lshiftrt:SI (match_operand:SI 2 "register_operand" "r") | |
3830 | (match_operand:SI 4 "const_int_operand" "n")) | |
3831 | (ashift:SI (match_operand:SI 1 "register_operand" "r") | |
3832 | (match_operand:SI 3 "const_int_operand" "n"))]))] | |
3833 | "INTVAL (operands[3]) + INTVAL (operands[4]) == 32" | |
3834 | "shd %1,%2,%4,%0" | |
c47decad | 3835 | [(set_attr "type" "shift") |
4c2164b7 | 3836 | (set_attr "length" "4")]) |
56a65d12 TG |
3837 | |
3838 | (define_insn "" | |
3839 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3840 | (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") | |
3841 | (match_operand:SI 2 "const_int_operand" "")) | |
3842 | (match_operand:SI 3 "const_int_operand" "")))] | |
3843 | "exact_log2 (1 + (INTVAL (operands[3]) >> (INTVAL (operands[2]) & 31))) >= 0" | |
3844 | "* | |
3845 | { | |
3846 | int cnt = INTVAL (operands[2]) & 31; | |
3847 | operands[3] = GEN_INT (exact_log2 (1 + (INTVAL (operands[3]) >> cnt))); | |
3848 | operands[2] = GEN_INT (31 - cnt); | |
3849 | return \"zdep %1,%2,%3,%0\"; | |
34f921d8 | 3850 | }" |
c47decad | 3851 | [(set_attr "type" "shift") |
4c2164b7 | 3852 | (set_attr "length" "4")]) |
c733e074 TM |
3853 | \f |
3854 | ;; Unconditional and other jump instructions. | |
3855 | ||
c1fab105 JL |
3856 | (define_insn "return" |
3857 | [(return)] | |
3858 | "hppa_can_use_return_insn_p ()" | |
3859 | "bv%* 0(%%r2)" | |
c47decad JL |
3860 | [(set_attr "type" "branch") |
3861 | (set_attr "length" "4")]) | |
c1fab105 | 3862 | |
2f95ebc2 | 3863 | ;; Use a different pattern for functions which have non-trivial |
b0213198 JL |
3864 | ;; epilogues so as not to confuse jump and reorg. |
3865 | (define_insn "return_internal" | |
3866 | [(use (reg:SI 2)) | |
3867 | (return)] | |
3868 | "" | |
3869 | "bv%* 0(%%r2)" | |
c47decad JL |
3870 | [(set_attr "type" "branch") |
3871 | (set_attr "length" "4")]) | |
b0213198 JL |
3872 | |
3873 | (define_expand "prologue" | |
3874 | [(const_int 0)] | |
3875 | "" | |
3876 | "hppa_expand_prologue ();DONE;") | |
3877 | ||
3878 | (define_expand "epilogue" | |
3879 | [(return)] | |
3880 | "" | |
3881 | " | |
3882 | { | |
2f95ebc2 | 3883 | /* Try to use the trivial return first. Else use the full |
b0213198 JL |
3884 | epilogue. */ |
3885 | if (hppa_can_use_return_insn_p ()) | |
3886 | emit_jump_insn (gen_return ()); | |
3887 | else | |
3888 | { | |
3889 | hppa_expand_epilogue (); | |
3890 | emit_jump_insn (gen_return_internal ()); | |
3891 | } | |
3892 | DONE; | |
3893 | }") | |
3894 | ||
3895 | ;; Special because we use the value placed in %r2 by the bl instruction | |
3896 | ;; from within its delay slot to set the value for the 2nd parameter to | |
3897 | ;; the call. | |
3898 | (define_insn "call_profiler" | |
3899 | [(unspec_volatile [(const_int 0)] 0) | |
3900 | (use (match_operand:SI 0 "const_int_operand" ""))] | |
3901 | "" | |
3902 | "bl _mcount,%%r2\;ldo %0(%%r2),%%r25" | |
c47decad JL |
3903 | [(set_attr "type" "multi") |
3904 | (set_attr "length" "8")]) | |
b0213198 | 3905 | |
f57f12c3 JL |
3906 | (define_insn "blockage" |
3907 | [(unspec_volatile [(const_int 2)] 0)] | |
3908 | "" | |
3909 | "" | |
3910 | [(set_attr "length" "0")]) | |
3911 | ||
746a9efa JL |
3912 | (define_insn "switch_jump" |
3913 | [(set:DI (pc) (label_ref (match_operand 0 "" "")))] | |
3914 | "" | |
3915 | "bl %l0,0%#" | |
3916 | [(set_attr "type" "uncond_branch") | |
3917 | (set_attr "length" "4")]) | |
3918 | ||
c733e074 TM |
3919 | (define_insn "jump" |
3920 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
3921 | "" | |
87c16668 JL |
3922 | "* |
3923 | { | |
3924 | extern int optimize; | |
3925 | /* An unconditional branch which can reach its target. */ | |
3926 | if (get_attr_length (insn) != 24 | |
3927 | && get_attr_length (insn) != 16) | |
3928 | return \"bl%* %l0,0\"; | |
3929 | ||
3930 | /* An unconditional branch which can not reach its target. | |
3931 | ||
3932 | We need to be able to use %r1 as a scratch register; however, | |
3933 | we can never be sure whether or not it's got a live value in | |
3934 | it. Therefore, we must restore its original value after the | |
3935 | jump. | |
3936 | ||
3937 | To make matters worse, we don't have a stack slot which we | |
3938 | can always clobber. sp-12/sp-16 shouldn't ever have a live | |
3939 | value during a non-optimizing compilation, so we use those | |
3940 | slots for now. We don't support very long branches when | |
3941 | optimizing -- they should be quite rare when optimizing. | |
3942 | ||
3943 | Really the way to go long term is a register scavenger; goto | |
3944 | the target of the jump and find a register which we can use | |
3945 | as a scratch to hold the value in %r1. */ | |
3946 | ||
3947 | /* We don't know how to register scavenge yet. */ | |
3948 | if (optimize) | |
3949 | abort (); | |
3950 | ||
3951 | /* First store %r1 into the stack. */ | |
3952 | output_asm_insn (\"stw %%r1,-16(%%r30)\", operands); | |
3953 | ||
3954 | /* Now load the target address into %r1 and do an indirect jump | |
3955 | to the value specified in %r1. Be careful to generate PIC | |
3956 | code as needed. */ | |
3957 | if (flag_pic) | |
3958 | { | |
3959 | rtx xoperands[2]; | |
3960 | xoperands[0] = operands[0]; | |
3961 | xoperands[1] = gen_label_rtx (); | |
3962 | ||
3963 | output_asm_insn (\"bl .+8,%%r1\\n\\taddil L'%l0-%l1,%%r1\", xoperands); | |
3964 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", | |
3965 | CODE_LABEL_NUMBER (xoperands[1])); | |
3966 | output_asm_insn (\"ldo R'%l0-%l1(%%r1),%%r1\\n\\tbv 0(%%r1)\", | |
3967 | xoperands); | |
3968 | } | |
3969 | else | |
3970 | output_asm_insn (\"ldil L'%l0,%%r1\\n\\tbe R'%l0(%%sr4,%%r1)\", operands);; | |
3971 | ||
3972 | /* And restore the value of %r1 in the delay slot. We're not optimizing, | |
3973 | so we know nothing else can be in the delay slot. */ | |
3974 | return \"ldw -16(%%r30),%%r1\"; | |
3975 | }" | |
f854c12c | 3976 | [(set_attr "type" "uncond_branch") |
c4bb6b38 | 3977 | (set_attr "pa_combine_type" "uncond_branch") |
f854c12c | 3978 | (set (attr "length") |
87c16668 JL |
3979 | (cond [(eq (symbol_ref "jump_in_call_delay (insn)") (const_int 1)) |
3980 | (if_then_else (lt (abs (minus (match_dup 0) | |
3981 | (plus (pc) (const_int 8)))) | |
3982 | (const_int 8184)) | |
3983 | (const_int 4) | |
3984 | (const_int 8)) | |
3985 | (ge (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) | |
3986 | (const_int 262100)) | |
3987 | (if_then_else (eq (symbol_ref "flag_pic") (const_int 0)) | |
3988 | (const_int 16) | |
3989 | (const_int 24))] | |
3990 | (const_int 4)))]) | |
c733e074 | 3991 | |
876662ef TG |
3992 | ;; Subroutines of "casesi". |
3993 | ;; operand 0 is index | |
3994 | ;; operand 1 is the minimum bound | |
3995 | ;; operand 2 is the maximum bound - minimum bound + 1 | |
3996 | ;; operand 3 is CODE_LABEL for the table; | |
3997 | ;; operand 4 is the CODE_LABEL to go to if index out of range. | |
3998 | ||
3999 | (define_expand "casesi" | |
4000 | [(match_operand:SI 0 "general_operand" "") | |
4001 | (match_operand:SI 1 "const_int_operand" "") | |
4002 | (match_operand:SI 2 "const_int_operand" "") | |
4003 | (match_operand 3 "" "") | |
4004 | (match_operand 4 "" "")] | |
4005 | "" | |
4006 | " | |
4007 | { | |
4008 | if (GET_CODE (operands[0]) != REG) | |
4009 | operands[0] = force_reg (SImode, operands[0]); | |
4010 | ||
4011 | if (operands[1] != const0_rtx) | |
4012 | { | |
4013 | rtx reg = gen_reg_rtx (SImode); | |
4014 | ||
6f672dc0 | 4015 | operands[1] = GEN_INT (-INTVAL (operands[1])); |
876662ef TG |
4016 | if (!INT_14_BITS (operands[1])) |
4017 | operands[1] = force_reg (SImode, operands[1]); | |
4018 | emit_insn (gen_addsi3 (reg, operands[0], operands[1])); | |
4019 | ||
4020 | operands[0] = reg; | |
4021 | } | |
4022 | ||
3e056efc | 4023 | if (!INT_5_BITS (operands[2])) |
876662ef TG |
4024 | operands[2] = force_reg (SImode, operands[2]); |
4025 | ||
3e056efc JL |
4026 | emit_insn (gen_cmpsi (operands[0], operands[2])); |
4027 | emit_jump_insn (gen_bgtu (operands[4])); | |
4028 | if (TARGET_BIG_SWITCH) | |
4029 | { | |
4030 | rtx temp = gen_reg_rtx (SImode); | |
4031 | emit_move_insn (temp, gen_rtx (PLUS, SImode, operands[0], operands[0])); | |
4032 | operands[0] = temp; | |
4033 | } | |
4034 | emit_jump_insn (gen_casesi0 (operands[0], operands[3])); | |
876662ef TG |
4035 | DONE; |
4036 | }") | |
4037 | ||
4038 | (define_insn "casesi0" | |
3e056efc JL |
4039 | [(set (pc) (plus:SI |
4040 | (mem:SI (plus:SI (pc) (match_operand 0 "register_operand" "r"))) | |
4041 | (label_ref (match_operand 1 "" ""))))] | |
c733e074 | 4042 | "" |
3e056efc | 4043 | "blr %0,0\;nop" |
c47decad | 4044 | [(set_attr "type" "multi") |
3e056efc | 4045 | (set_attr "length" "8")]) |
876662ef | 4046 | |
c733e074 TM |
4047 | ;; Need nops for the calls because execution is supposed to continue |
4048 | ;; past; we don't want to nullify an instruction that we need. | |
4049 | ;;- jump to subroutine | |
4050 | ||
4051 | (define_expand "call" | |
2f95ebc2 TG |
4052 | [(parallel [(call (match_operand:SI 0 "" "") |
4053 | (match_operand 1 "" "")) | |
4054 | (clobber (reg:SI 2))])] | |
4055 | "" | |
4056 | " | |
c733e074 | 4057 | { |
4d72c241 | 4058 | rtx op; |
6bb36601 | 4059 | rtx call_insn; |
2f95ebc2 | 4060 | |
279c9bde | 4061 | if (TARGET_PORTABLE_RUNTIME) |
4d72c241 | 4062 | op = force_reg (SImode, XEXP (operands[0], 0)); |
5cf2759e | 4063 | else |
4d72c241 | 4064 | op = XEXP (operands[0], 0); |
5d5c8541 JL |
4065 | |
4066 | /* Use two different patterns for calls to explicitly named functions | |
4067 | and calls through function pointers. This is necessary as these two | |
4068 | types of calls use different calling conventions, and CSE might try | |
4069 | to change the named call into an indirect call in some cases (using | |
4070 | two patterns keeps CSE from performing this optimization). */ | |
4071 | if (GET_CODE (op) == SYMBOL_REF) | |
6bb36601 | 4072 | call_insn = emit_call_insn (gen_call_internal_symref (op, operands[1])); |
5d5c8541 | 4073 | else |
6a73009d JL |
4074 | { |
4075 | rtx tmpreg = gen_rtx (REG, SImode, 22); | |
4076 | emit_move_insn (tmpreg, force_reg (SImode, op)); | |
4077 | call_insn = emit_call_insn (gen_call_internal_reg (operands[1])); | |
4078 | } | |
5d5c8541 | 4079 | |
4d72c241 JL |
4080 | if (flag_pic) |
4081 | { | |
6bb36601 JL |
4082 | use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx); |
4083 | ||
10786997 RK |
4084 | /* After each call we must restore the PIC register, even if it |
4085 | doesn't appear to be used. | |
4086 | ||
4087 | This will set regs_ever_live for the callee saved register we | |
4088 | stored the PIC register in. */ | |
4089 | emit_move_insn (pic_offset_table_rtx, | |
4090 | gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM_SAVED)); | |
4091 | emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); | |
6a73009d JL |
4092 | |
4093 | /* Gross. We have to keep the scheduler from moving the restore | |
4094 | of the PIC register away from the call. SCHED_GROUP_P is | |
4095 | supposed to do this, but for some reason the compiler will | |
4096 | go into an infinite loop when we use that. | |
4097 | ||
4098 | This method (blockage insn) may make worse code (then again | |
4099 | it may not since calls are nearly blockages anyway), but at | |
4100 | least it should work. */ | |
4101 | emit_insn (gen_blockage ()); | |
4d72c241 JL |
4102 | } |
4103 | DONE; | |
c733e074 TM |
4104 | }") |
4105 | ||
5d5c8541 | 4106 | (define_insn "call_internal_symref" |
2f95ebc2 TG |
4107 | [(call (mem:SI (match_operand:SI 0 "call_operand_address" "")) |
4108 | (match_operand 1 "" "i")) | |
4109 | (clobber (reg:SI 2)) | |
4110 | (use (const_int 0))] | |
279c9bde | 4111 | "! TARGET_PORTABLE_RUNTIME" |
2f95ebc2 | 4112 | "* |
c733e074 | 4113 | { |
5d5c8541 | 4114 | output_arg_descriptor (insn); |
f854c12c | 4115 | return output_call (insn, operands[0], gen_rtx (REG, SImode, 2)); |
c733e074 | 4116 | }" |
2f95ebc2 | 4117 | [(set_attr "type" "call") |
279c9bde | 4118 | (set (attr "length") |
6a73009d JL |
4119 | ;; If we're sure that we can either reach the target or that the |
4120 | ;; linker can use a long-branch stub, then the length is 4 bytes. | |
4121 | ;; | |
4122 | ;; For long-calls the length will be either 52 bytes (non-pic) | |
4123 | ;; or 68 bytes (pic). */ | |
4124 | ;; Else we have to use a long-call; | |
279c9bde JL |
4125 | (if_then_else (lt (plus (symbol_ref "total_code_bytes") (pc)) |
4126 | (const_int 240000)) | |
4127 | (const_int 4) | |
6a73009d | 4128 | (if_then_else (eq (symbol_ref "flag_pic") |
279c9bde | 4129 | (const_int 0)) |
6a73009d JL |
4130 | (const_int 52) |
4131 | (const_int 68))))]) | |
5d5c8541 JL |
4132 | |
4133 | (define_insn "call_internal_reg" | |
6a73009d JL |
4134 | [(call (mem:SI (reg:SI 22)) |
4135 | (match_operand 0 "" "i")) | |
2f95ebc2 TG |
4136 | (clobber (reg:SI 2)) |
4137 | (use (const_int 1))] | |
4138 | "" | |
f726ea7d JL |
4139 | "* |
4140 | { | |
6a73009d | 4141 | rtx xoperands[2]; |
105ce113 | 4142 | |
6a73009d | 4143 | /* First the special case for kernels, level 0 systems, etc. */ |
3aba034b | 4144 | if (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS) |
6a73009d JL |
4145 | return \"ble 0(%%sr4,%%r22)\;copy %%r31,%%r2\"; |
4146 | ||
4147 | /* Now the normal case -- we can reach $$dyncall directly or | |
4148 | we're sure that we can get there via a long-branch stub. | |
4149 | ||
4150 | No need to check target flags as the length uniquely identifies | |
4151 | the remaining cases. */ | |
4152 | if (get_attr_length (insn) == 8) | |
4153 | return \".CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\"; | |
4154 | ||
4155 | /* Long millicode call, but we are not generating PIC or portable runtime | |
4156 | code. */ | |
4157 | if (get_attr_length (insn) == 12) | |
ebcf525f | 4158 | return \".CALL\\tARGW0=GR\;ldil L%%$$dyncall,%%r2\;ble R%%$$dyncall(%%sr4,%%r2)\;copy %%r31,%%r2\"; |
6a73009d JL |
4159 | |
4160 | /* Long millicode call for portable runtime. */ | |
4161 | if (get_attr_length (insn) == 20) | |
4162 | return \"ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\"; | |
4163 | ||
4164 | /* If we're generating PIC code. */ | |
4165 | xoperands[0] = operands[0]; | |
4166 | xoperands[1] = gen_label_rtx (); | |
4167 | output_asm_insn (\"bl .+8,%%r1\", xoperands); | |
4168 | output_asm_insn (\"addil L%%$$dyncall-%1,%%r1\", xoperands); | |
4169 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", | |
4170 | CODE_LABEL_NUMBER (xoperands[1])); | |
4171 | output_asm_insn (\"ldo R%%$$dyncall-%1(%%r1),%%r1\", xoperands); | |
4172 | output_asm_insn (\"blr 0,%%r2\", xoperands); | |
4173 | output_asm_insn (\"bv,n 0(%%r1)\\n\\tnop\", xoperands); | |
4174 | return \"\"; | |
f726ea7d | 4175 | }" |
2f95ebc2 | 4176 | [(set_attr "type" "dyncall") |
279c9bde | 4177 | (set (attr "length") |
6a73009d JL |
4178 | (cond [ |
4179 | ;; First NO_SPACE_REGS | |
3aba034b | 4180 | (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") |
6a73009d JL |
4181 | (const_int 0)) |
4182 | (const_int 8) | |
4183 | ||
4184 | ;; Target (or stub) within reach | |
4185 | (and (lt (plus (symbol_ref "total_code_bytes") (pc)) | |
4186 | (const_int 240000)) | |
4187 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
4188 | (const_int 0))) | |
4189 | (const_int 8) | |
4190 | ||
4191 | ;; Out of reach, but not PIC or PORTABLE_RUNTIME | |
4192 | (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
4193 | (const_int 0)) | |
4194 | (eq (symbol_ref "flag_pic") | |
4195 | (const_int 0))) | |
4196 | (const_int 12) | |
4197 | ||
4198 | (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
4199 | (const_int 0)) | |
4200 | (const_int 20)] | |
4201 | ||
4202 | ;; Out of range PIC case | |
4203 | (const_int 24)))]) | |
c733e074 TM |
4204 | |
4205 | (define_expand "call_value" | |
4206 | [(parallel [(set (match_operand 0 "" "") | |
4207 | (call (match_operand:SI 1 "" "") | |
4208 | (match_operand 2 "" ""))) | |
c733e074 | 4209 | (clobber (reg:SI 2))])] |
c733e074 TM |
4210 | "" |
4211 | " | |
4212 | { | |
4d72c241 | 4213 | rtx op; |
6bb36601 | 4214 | rtx call_insn; |
2f95ebc2 | 4215 | |
279c9bde | 4216 | if (TARGET_PORTABLE_RUNTIME) |
4d72c241 | 4217 | op = force_reg (SImode, XEXP (operands[1], 0)); |
5cf2759e | 4218 | else |
4d72c241 | 4219 | op = XEXP (operands[1], 0); |
5d5c8541 JL |
4220 | |
4221 | /* Use two different patterns for calls to explicitly named functions | |
4222 | and calls through function pointers. This is necessary as these two | |
4223 | types of calls use different calling conventions, and CSE might try | |
4224 | to change the named call into an indirect call in some cases (using | |
4225 | two patterns keeps CSE from performing this optimization). */ | |
4226 | if (GET_CODE (op) == SYMBOL_REF) | |
6bb36601 JL |
4227 | call_insn = emit_call_insn (gen_call_value_internal_symref (operands[0], |
4228 | op, | |
4229 | operands[2])); | |
5d5c8541 | 4230 | else |
6a73009d JL |
4231 | { |
4232 | rtx tmpreg = gen_rtx (REG, SImode, 22); | |
4233 | emit_move_insn (tmpreg, force_reg (SImode, op)); | |
4234 | call_insn = emit_call_insn (gen_call_value_internal_reg (operands[0], | |
4235 | operands[2])); | |
4236 | } | |
4d72c241 JL |
4237 | if (flag_pic) |
4238 | { | |
6bb36601 JL |
4239 | use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx); |
4240 | ||
10786997 RK |
4241 | /* After each call we must restore the PIC register, even if it |
4242 | doesn't appear to be used. | |
4243 | ||
4244 | This will set regs_ever_live for the callee saved register we | |
4245 | stored the PIC register in. */ | |
4246 | emit_move_insn (pic_offset_table_rtx, | |
4247 | gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM_SAVED)); | |
4248 | emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); | |
31cc58e9 RK |
4249 | |
4250 | /* Gross. We have to keep the scheduler from moving the restore | |
4251 | of the PIC register away from the call. SCHED_GROUP_P is | |
4252 | supposed to do this, but for some reason the compiler will | |
4253 | go into an infinite loop when we use that. | |
4254 | ||
4255 | This method (blockage insn) may make worse code (then again | |
4256 | it may not since calls are nearly blockages anyway), but at | |
4257 | least it should work. */ | |
4258 | emit_insn (gen_blockage ()); | |
4d72c241 JL |
4259 | } |
4260 | DONE; | |
c733e074 TM |
4261 | }") |
4262 | ||
5d5c8541 | 4263 | (define_insn "call_value_internal_symref" |
0b27d5dd | 4264 | [(set (match_operand 0 "" "=rf") |
5d5c8541 JL |
4265 | (call (mem:SI (match_operand:SI 1 "call_operand_address" "")) |
4266 | (match_operand 2 "" "i"))) | |
4267 | (clobber (reg:SI 2)) | |
4268 | (use (const_int 0))] | |
c733e074 | 4269 | ;;- Don't use operand 1 for most machines. |
279c9bde | 4270 | "! TARGET_PORTABLE_RUNTIME" |
c733e074 TM |
4271 | "* |
4272 | { | |
5d5c8541 | 4273 | output_arg_descriptor (insn); |
f854c12c | 4274 | return output_call (insn, operands[1], gen_rtx (REG, SImode, 2)); |
c733e074 | 4275 | }" |
2f95ebc2 | 4276 | [(set_attr "type" "call") |
279c9bde | 4277 | (set (attr "length") |
6a73009d JL |
4278 | ;; If we're sure that we can either reach the target or that the |
4279 | ;; linker can use a long-branch stub, then the length is 4 bytes. | |
4280 | ;; | |
4281 | ;; For long-calls the length will be either 52 bytes (non-pic) | |
4282 | ;; or 68 bytes (pic). */ | |
4283 | ;; Else we have to use a long-call; | |
279c9bde JL |
4284 | (if_then_else (lt (plus (symbol_ref "total_code_bytes") (pc)) |
4285 | (const_int 240000)) | |
4286 | (const_int 4) | |
6a73009d | 4287 | (if_then_else (eq (symbol_ref "flag_pic") |
279c9bde | 4288 | (const_int 0)) |
6a73009d JL |
4289 | (const_int 52) |
4290 | (const_int 68))))]) | |
5d5c8541 JL |
4291 | |
4292 | (define_insn "call_value_internal_reg" | |
0b27d5dd | 4293 | [(set (match_operand 0 "" "=rf") |
6a73009d JL |
4294 | (call (mem:SI (reg:SI 22)) |
4295 | (match_operand 1 "" "i"))) | |
5d5c8541 JL |
4296 | (clobber (reg:SI 2)) |
4297 | (use (const_int 1))] | |
5d5c8541 | 4298 | "" |
f726ea7d JL |
4299 | "* |
4300 | { | |
6a73009d JL |
4301 | rtx xoperands[2]; |
4302 | ||
4303 | /* First the special case for kernels, level 0 systems, etc. */ | |
3aba034b | 4304 | if (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS) |
6a73009d JL |
4305 | return \"ble 0(%%sr4,%%r22)\;copy %%r31,%%r2\"; |
4306 | ||
4307 | /* Now the normal case -- we can reach $$dyncall directly or | |
4308 | we're sure that we can get there via a long-branch stub. | |
4309 | ||
4310 | No need to check target flags as the length uniquely identifies | |
4311 | the remaining cases. */ | |
4312 | if (get_attr_length (insn) == 8) | |
4313 | return \".CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\"; | |
4314 | ||
4315 | /* Long millicode call, but we are not generating PIC or portable runtime | |
4316 | code. */ | |
4317 | if (get_attr_length (insn) == 12) | |
4318 | return \".CALL\\tARGW0=GR\;ldil L%%$$dyncall,%%r2\;ble R%%$$dyncall(%%sr4,%%r2)\;copy %%r31,%%r2\"; | |
4319 | ||
4320 | /* Long millicode call for portable runtime. */ | |
4321 | if (get_attr_length (insn) == 20) | |
4322 | return \"ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\"; | |
4323 | ||
4324 | /* If we're generating PIC code. */ | |
4325 | xoperands[0] = operands[1]; | |
4326 | xoperands[1] = gen_label_rtx (); | |
4327 | output_asm_insn (\"bl .+8,%%r1\", xoperands); | |
4328 | output_asm_insn (\"addil L%%$$dyncall-%1,%%r1\", xoperands); | |
4329 | ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", | |
4330 | CODE_LABEL_NUMBER (xoperands[1])); | |
4331 | output_asm_insn (\"ldo R%%$$dyncall-%1(%%r1),%%r1\", xoperands); | |
4332 | output_asm_insn (\"blr 0,%%r2\", xoperands); | |
4333 | output_asm_insn (\"bv,n 0(%%r1)\\n\\tnop\", xoperands); | |
4334 | return \"\"; | |
f726ea7d | 4335 | }" |
2f95ebc2 | 4336 | [(set_attr "type" "dyncall") |
279c9bde | 4337 | (set (attr "length") |
6a73009d JL |
4338 | (cond [ |
4339 | ;; First NO_SPACE_REGS | |
3aba034b | 4340 | (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") |
6a73009d JL |
4341 | (const_int 0)) |
4342 | (const_int 8) | |
4343 | ||
4344 | ;; Target (or stub) within reach | |
4345 | (and (lt (plus (symbol_ref "total_code_bytes") (pc)) | |
4346 | (const_int 240000)) | |
4347 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
4348 | (const_int 0))) | |
4349 | (const_int 8) | |
4350 | ||
4351 | ;; Out of reach, but not PIC or PORTABLE_RUNTIME | |
4352 | (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
4353 | (const_int 0)) | |
4354 | (eq (symbol_ref "flag_pic") | |
4355 | (const_int 0))) | |
4356 | (const_int 12) | |
4357 | ||
4358 | (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
4359 | (const_int 0)) | |
4360 | (const_int 20)] | |
4361 | ||
4362 | ;; Out of range PIC case | |
4363 | (const_int 24)))]) | |
c733e074 | 4364 | |
dfeddf46 JL |
4365 | ;; Call subroutine returning any type. |
4366 | ||
4367 | (define_expand "untyped_call" | |
4368 | [(parallel [(call (match_operand 0 "" "") | |
4369 | (const_int 0)) | |
4370 | (match_operand 1 "" "") | |
4371 | (match_operand 2 "" "")])] | |
4372 | "" | |
4373 | " | |
4374 | { | |
4375 | int i; | |
4376 | ||
4377 | emit_call_insn (gen_call (operands[0], const0_rtx)); | |
4378 | ||
4379 | for (i = 0; i < XVECLEN (operands[2], 0); i++) | |
4380 | { | |
4381 | rtx set = XVECEXP (operands[2], 0, i); | |
4382 | emit_move_insn (SET_DEST (set), SET_SRC (set)); | |
4383 | } | |
4384 | ||
4385 | /* The optimizer does not know that the call sets the function value | |
4386 | registers we stored in the result block. We avoid problems by | |
4387 | claiming that all hard registers are used and clobbered at this | |
4388 | point. */ | |
4389 | emit_insn (gen_blockage ()); | |
4390 | ||
4391 | DONE; | |
4392 | }") | |
c733e074 TM |
4393 | (define_insn "nop" |
4394 | [(const_int 0)] | |
4395 | "" | |
c47decad JL |
4396 | "nop" |
4397 | [(set_attr "type" "move") | |
4398 | (set_attr "length" "4")]) | |
c733e074 | 4399 | |
ad238e4b JL |
4400 | ;; These are just placeholders so we know where branch tables |
4401 | ;; begin and end. | |
4402 | (define_insn "begin_brtab" | |
4403 | [(const_int 1)] | |
251ffdee JL |
4404 | "" |
4405 | "* | |
4406 | { | |
4407 | /* Only GAS actually supports this pseudo-op. */ | |
4408 | if (TARGET_GAS) | |
4409 | return \".begin_brtab\"; | |
4410 | else | |
4411 | return \"\"; | |
4412 | }" | |
ad238e4b JL |
4413 | [(set_attr "type" "move") |
4414 | (set_attr "length" "0")]) | |
4415 | ||
4416 | (define_insn "end_brtab" | |
4417 | [(const_int 2)] | |
251ffdee JL |
4418 | "" |
4419 | "* | |
4420 | { | |
4421 | /* Only GAS actually supports this pseudo-op. */ | |
4422 | if (TARGET_GAS) | |
4423 | return \".end_brtab\"; | |
4424 | else | |
4425 | return \"\"; | |
4426 | }" | |
ad238e4b JL |
4427 | [(set_attr "type" "move") |
4428 | (set_attr "length" "0")]) | |
4429 | ||
c733e074 TM |
4430 | ;;; Hope this is only within a function... |
4431 | (define_insn "indirect_jump" | |
4432 | [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
4433 | "" | |
2f95ebc2 | 4434 | "bv%* 0(%0)" |
c47decad JL |
4435 | [(set_attr "type" "branch") |
4436 | (set_attr "length" "4")]) | |
c733e074 TM |
4437 | |
4438 | (define_insn "extzv" | |
4439 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4440 | (zero_extract:SI (match_operand:SI 1 "register_operand" "r") | |
4441 | (match_operand:SI 2 "uint5_operand" "") | |
4442 | (match_operand:SI 3 "uint5_operand" "")))] | |
4443 | "" | |
c47decad JL |
4444 | "extru %1,%3+%2-1,%2,%0" |
4445 | [(set_attr "type" "shift") | |
4446 | (set_attr "length" "4")]) | |
c733e074 | 4447 | |
2f95ebc2 TG |
4448 | (define_insn "" |
4449 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4450 | (zero_extract:SI (match_operand:SI 1 "register_operand" "r") | |
4451 | (const_int 1) | |
4452 | (match_operand:SI 3 "register_operand" "q")))] | |
4453 | "" | |
c47decad JL |
4454 | "vextru %1,1,%0" |
4455 | [(set_attr "type" "shift") | |
4456 | (set_attr "length" "4")]) | |
2f95ebc2 | 4457 | |
c733e074 TM |
4458 | (define_insn "extv" |
4459 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4460 | (sign_extract:SI (match_operand:SI 1 "register_operand" "r") | |
4461 | (match_operand:SI 2 "uint5_operand" "") | |
4462 | (match_operand:SI 3 "uint5_operand" "")))] | |
4463 | "" | |
c47decad JL |
4464 | "extrs %1,%3+%2-1,%2,%0" |
4465 | [(set_attr "type" "shift") | |
4466 | (set_attr "length" "4")]) | |
c733e074 | 4467 | |
2f95ebc2 TG |
4468 | (define_insn "" |
4469 | [(set (match_operand:SI 0 "register_operand" "=r") | |
4470 | (sign_extract:SI (match_operand:SI 1 "register_operand" "r") | |
4471 | (const_int 1) | |
4472 | (match_operand:SI 3 "register_operand" "q")))] | |
4473 | "" | |
c47decad JL |
4474 | "vextrs %1,1,%0" |
4475 | [(set_attr "type" "shift") | |
4476 | (set_attr "length" "4")]) | |
2f95ebc2 | 4477 | |
c733e074 | 4478 | (define_insn "insv" |
51c2b9d1 | 4479 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r") |
c733e074 TM |
4480 | (match_operand:SI 1 "uint5_operand" "") |
4481 | (match_operand:SI 2 "uint5_operand" "")) | |
51c2b9d1 | 4482 | (match_operand:SI 3 "arith5_operand" "r,L"))] |
c733e074 | 4483 | "" |
51c2b9d1 TG |
4484 | "@ |
4485 | dep %3,%2+%1-1,%1,%0 | |
c47decad JL |
4486 | depi %3,%2+%1-1,%1,%0" |
4487 | [(set_attr "type" "shift,shift") | |
4488 | (set_attr "length" "4,4")]) | |
51c2b9d1 TG |
4489 | |
4490 | ;; Optimize insertion of const_int values of type 1...1xxxx. | |
4491 | (define_insn "" | |
4492 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") | |
4493 | (match_operand:SI 1 "uint5_operand" "") | |
4494 | (match_operand:SI 2 "uint5_operand" "")) | |
4495 | (match_operand:SI 3 "const_int_operand" ""))] | |
4496 | "(INTVAL (operands[3]) & 0x10) != 0 && | |
4497 | (~INTVAL (operands[3]) & (1L << INTVAL (operands[1])) - 1 & ~0xf) == 0" | |
4498 | "* | |
4499 | { | |
6f672dc0 | 4500 | operands[3] = GEN_INT ((INTVAL (operands[3]) & 0xf) - 0x10); |
51c2b9d1 | 4501 | return \"depi %3,%2+%1-1,%1,%0\"; |
c47decad JL |
4502 | }" |
4503 | [(set_attr "type" "shift") | |
4504 | (set_attr "length" "4")]) | |
c733e074 | 4505 | |
53a66787 TG |
4506 | ;; This insn is used for some loop tests, typically loops reversed when |
4507 | ;; strength reduction is used. It is actually created when the instruction | |
4508 | ;; combination phase combines the special loop test. Since this insn | |
4509 | ;; is both a jump insn and has an output, it must deal with it's own | |
4510 | ;; reloads, hence the `m' constraints. The `!' constraints direct reload | |
4511 | ;; to not choose the register alternatives in the event a reload is needed. | |
53a66787 TG |
4512 | (define_insn "decrement_and_branch_until_zero" |
4513 | [(set (pc) | |
4514 | (if_then_else | |
6d9d0ca1 | 4515 | (match_operator 2 "comparison_operator" |
0b27d5dd | 4516 | [(plus:SI (match_operand:SI 0 "register_operand" "+!r,!*f,!*m") |
f65590a9 | 4517 | (match_operand:SI 1 "int5_operand" "L,L,L")) |
6d9d0ca1 JL |
4518 | (const_int 0)]) |
4519 | (label_ref (match_operand 3 "" "")) | |
53a66787 TG |
4520 | (pc))) |
4521 | (set (match_dup 0) | |
6d9d0ca1 | 4522 | (plus:SI (match_dup 0) (match_dup 1))) |
f65590a9 JL |
4523 | (clobber (match_scratch:SI 4 "=X,r,r"))] |
4524 | "" | |
6f45095d | 4525 | "* return output_dbra (operands, insn, which_alternative); " |
2f95ebc2 | 4526 | ;; Do not expect to understand this the first time through. |
98b2d887 JL |
4527 | [(set_attr "type" "cbranch,multi,multi") |
4528 | (set (attr "length") | |
4529 | (if_then_else (eq_attr "alternative" "0") | |
4530 | ;; Loop counter in register case | |
4c2164b7 JL |
4531 | ;; Short branch has length of 4 |
4532 | ;; Long branch has length of 8 | |
4533 | (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) | |
6a73009d | 4534 | (const_int 8184)) |
4c2164b7 JL |
4535 | (const_int 4) |
4536 | (const_int 8)) | |
f65590a9 | 4537 | |
f65590a9 JL |
4538 | ;; Loop counter in FP reg case. |
4539 | ;; Extra goo to deal with additional reload insns. | |
4540 | (if_then_else (eq_attr "alternative" "1") | |
4541 | (if_then_else (lt (match_dup 3) (pc)) | |
2f95ebc2 | 4542 | (if_then_else |
4c2164b7 | 4543 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24)))) |
6a73009d | 4544 | (const_int 8184)) |
4c2164b7 JL |
4545 | (const_int 24) |
4546 | (const_int 28)) | |
2f95ebc2 | 4547 | (if_then_else |
4c2164b7 | 4548 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) |
6a73009d | 4549 | (const_int 8184)) |
4c2164b7 JL |
4550 | (const_int 24) |
4551 | (const_int 28))) | |
f65590a9 JL |
4552 | ;; Loop counter in memory case. |
4553 | ;; Extra goo to deal with additional reload insns. | |
4554 | (if_then_else (lt (match_dup 3) (pc)) | |
2f95ebc2 | 4555 | (if_then_else |
4c2164b7 | 4556 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) |
6a73009d | 4557 | (const_int 8184)) |
4c2164b7 JL |
4558 | (const_int 12) |
4559 | (const_int 16)) | |
2f95ebc2 | 4560 | (if_then_else |
4c2164b7 | 4561 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) |
6a73009d | 4562 | (const_int 8184)) |
4c2164b7 JL |
4563 | (const_int 12) |
4564 | (const_int 16))))))]) | |
53a66787 | 4565 | |
98b2d887 JL |
4566 | (define_insn "" |
4567 | [(set (pc) | |
4568 | (if_then_else | |
4569 | (match_operator 2 "movb_comparison_operator" | |
b1092901 | 4570 | [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)]) |
98b2d887 JL |
4571 | (label_ref (match_operand 3 "" "")) |
4572 | (pc))) | |
b1092901 | 4573 | (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m,!*q") |
98b2d887 JL |
4574 | (match_dup 1))] |
4575 | "" | |
4576 | "* return output_movb (operands, insn, which_alternative, 0); " | |
2f95ebc2 | 4577 | ;; Do not expect to understand this the first time through. |
b1092901 | 4578 | [(set_attr "type" "cbranch,multi,multi,multi") |
98b2d887 JL |
4579 | (set (attr "length") |
4580 | (if_then_else (eq_attr "alternative" "0") | |
4581 | ;; Loop counter in register case | |
4c2164b7 JL |
4582 | ;; Short branch has length of 4 |
4583 | ;; Long branch has length of 8 | |
4584 | (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) | |
6a73009d | 4585 | (const_int 8184)) |
4c2164b7 JL |
4586 | (const_int 4) |
4587 | (const_int 8)) | |
98b2d887 JL |
4588 | |
4589 | ;; Loop counter in FP reg case. | |
4590 | ;; Extra goo to deal with additional reload insns. | |
4591 | (if_then_else (eq_attr "alternative" "1") | |
4592 | (if_then_else (lt (match_dup 3) (pc)) | |
2f95ebc2 | 4593 | (if_then_else |
4c2164b7 | 4594 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) |
6a73009d | 4595 | (const_int 8184)) |
4c2164b7 JL |
4596 | (const_int 12) |
4597 | (const_int 16)) | |
2f95ebc2 | 4598 | (if_then_else |
4c2164b7 | 4599 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) |
6a73009d | 4600 | (const_int 8184)) |
4c2164b7 JL |
4601 | (const_int 12) |
4602 | (const_int 16))) | |
b1092901 | 4603 | ;; Loop counter in memory or sar case. |
98b2d887 | 4604 | ;; Extra goo to deal with additional reload insns. |
2f95ebc2 | 4605 | (if_then_else |
4c2164b7 | 4606 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) |
6a73009d | 4607 | (const_int 8184)) |
4c2164b7 JL |
4608 | (const_int 8) |
4609 | (const_int 12)))))]) | |
98b2d887 JL |
4610 | |
4611 | ;; Handle negated branch. | |
4612 | (define_insn "" | |
4613 | [(set (pc) | |
4614 | (if_then_else | |
4615 | (match_operator 2 "movb_comparison_operator" | |
b1092901 | 4616 | [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)]) |
98b2d887 JL |
4617 | (pc) |
4618 | (label_ref (match_operand 3 "" "")))) | |
b1092901 | 4619 | (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m,!*q") |
98b2d887 JL |
4620 | (match_dup 1))] |
4621 | "" | |
4622 | "* return output_movb (operands, insn, which_alternative, 1); " | |
2f95ebc2 | 4623 | ;; Do not expect to understand this the first time through. |
b1092901 | 4624 | [(set_attr "type" "cbranch,multi,multi,multi") |
98b2d887 JL |
4625 | (set (attr "length") |
4626 | (if_then_else (eq_attr "alternative" "0") | |
4627 | ;; Loop counter in register case | |
4c2164b7 JL |
4628 | ;; Short branch has length of 4 |
4629 | ;; Long branch has length of 8 | |
4630 | (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) | |
6a73009d | 4631 | (const_int 8184)) |
4c2164b7 JL |
4632 | (const_int 4) |
4633 | (const_int 8)) | |
98b2d887 JL |
4634 | |
4635 | ;; Loop counter in FP reg case. | |
4636 | ;; Extra goo to deal with additional reload insns. | |
4637 | (if_then_else (eq_attr "alternative" "1") | |
4638 | (if_then_else (lt (match_dup 3) (pc)) | |
2f95ebc2 | 4639 | (if_then_else |
4c2164b7 | 4640 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) |
6a73009d | 4641 | (const_int 8184)) |
4c2164b7 JL |
4642 | (const_int 12) |
4643 | (const_int 16)) | |
2f95ebc2 | 4644 | (if_then_else |
4c2164b7 | 4645 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) |
6a73009d | 4646 | (const_int 8184)) |
4c2164b7 JL |
4647 | (const_int 12) |
4648 | (const_int 16))) | |
b1092901 | 4649 | ;; Loop counter in memory or SAR case. |
98b2d887 | 4650 | ;; Extra goo to deal with additional reload insns. |
2f95ebc2 | 4651 | (if_then_else |
4c2164b7 | 4652 | (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) |
6a73009d | 4653 | (const_int 8184)) |
4c2164b7 JL |
4654 | (const_int 8) |
4655 | (const_int 12)))))]) | |
98b2d887 | 4656 | |
e45539c0 JL |
4657 | ;; The next several patterns (parallel_addb, parallel_movb, fmpyadd and |
4658 | ;; fmpysub aren't currently used by the FSF sources, but will be soon. | |
4659 | ;; | |
4660 | ;; They're in the FSF tree for documentation and to make Cygnus<->FSF | |
4661 | ;; merging easier. | |
4662 | (define_insn "" | |
4663 | [(set (pc) (label_ref (match_operand 3 "" "" ))) | |
4664 | (set (match_operand:SI 0 "register_operand" "=r") | |
4665 | (plus:SI (match_operand:SI 1 "register_operand" "r") | |
4666 | (match_operand:SI 2 "ireg_or_int5_operand" "rL")))] | |
4667 | "reload_completed && operands[0] == operands[1] || operands[0] == operands[2]" | |
4668 | "* | |
4669 | { | |
4670 | return output_parallel_addb (operands, get_attr_length (insn)); | |
4671 | }" | |
4672 | [(set_attr "type" "parallel_branch") | |
4673 | (set (attr "length") | |
4674 | (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) | |
4675 | (const_int 8184)) | |
4676 | (const_int 4) | |
4677 | (const_int 8)))]) | |
4678 | ||
4679 | (define_insn "" | |
4680 | [(set (pc) (label_ref (match_operand 2 "" "" ))) | |
4681 | (set (match_operand:SF 0 "register_operand" "=r") | |
4682 | (match_operand:SF 1 "ireg_or_int5_operand" "rL"))] | |
4683 | "reload_completed" | |
4684 | "* | |
4685 | { | |
4686 | return output_parallel_movb (operands, get_attr_length (insn)); | |
4687 | }" | |
4688 | [(set_attr "type" "parallel_branch") | |
4689 | (set (attr "length") | |
4690 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
4691 | (const_int 8184)) | |
4692 | (const_int 4) | |
4693 | (const_int 8)))]) | |
4694 | ||
4695 | (define_insn "" | |
4696 | [(set (pc) (label_ref (match_operand 2 "" "" ))) | |
4697 | (set (match_operand:SI 0 "register_operand" "=r") | |
4698 | (match_operand:SI 1 "ireg_or_int5_operand" "rL"))] | |
4699 | "reload_completed" | |
4700 | "* | |
4701 | { | |
4702 | return output_parallel_movb (operands, get_attr_length (insn)); | |
4703 | }" | |
4704 | [(set_attr "type" "parallel_branch") | |
4705 | (set (attr "length") | |
4706 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
4707 | (const_int 8184)) | |
4708 | (const_int 4) | |
4709 | (const_int 8)))]) | |
4710 | ||
4711 | (define_insn "" | |
4712 | [(set (pc) (label_ref (match_operand 2 "" "" ))) | |
4713 | (set (match_operand:HI 0 "register_operand" "=r") | |
4714 | (match_operand:HI 1 "ireg_or_int5_operand" "rL"))] | |
4715 | "reload_completed" | |
4716 | "* | |
4717 | { | |
4718 | return output_parallel_movb (operands, get_attr_length (insn)); | |
4719 | }" | |
4720 | [(set_attr "type" "parallel_branch") | |
4721 | (set (attr "length") | |
4722 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
4723 | (const_int 8184)) | |
4724 | (const_int 4) | |
4725 | (const_int 8)))]) | |
4726 | ||
4727 | (define_insn "" | |
4728 | [(set (pc) (label_ref (match_operand 2 "" "" ))) | |
4729 | (set (match_operand:QI 0 "register_operand" "=r") | |
4730 | (match_operand:QI 1 "ireg_or_int5_operand" "rL"))] | |
4731 | "reload_completed" | |
4732 | "* | |
4733 | { | |
4734 | return output_parallel_movb (operands, get_attr_length (insn)); | |
4735 | }" | |
4736 | [(set_attr "type" "parallel_branch") | |
4737 | (set (attr "length") | |
4738 | (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) | |
4739 | (const_int 8184)) | |
4740 | (const_int 4) | |
4741 | (const_int 8)))]) | |
4742 | ||
e45539c0 JL |
4743 | (define_insn "" |
4744 | [(set (match_operand 0 "register_operand" "=f") | |
4745 | (mult (match_operand 1 "register_operand" "f") | |
4746 | (match_operand 2 "register_operand" "f"))) | |
4747 | (set (match_operand 3 "register_operand" "+f") | |
4748 | (plus (match_operand 4 "register_operand" "f") | |
4749 | (match_operand 5 "register_operand" "f")))] | |
4750 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT | |
4751 | && reload_completed && fmpyaddoperands (operands)" | |
4752 | "* | |
4753 | { | |
4754 | if (GET_MODE (operands[0]) == DFmode) | |
4755 | { | |
4756 | if (rtx_equal_p (operands[3], operands[5])) | |
4757 | return \"fmpyadd,dbl %1,%2,%0,%4,%3\"; | |
4758 | else | |
4759 | return \"fmpyadd,dbl %1,%2,%0,%5,%3\"; | |
4760 | } | |
4761 | else | |
4762 | { | |
4763 | if (rtx_equal_p (operands[3], operands[5])) | |
4764 | return \"fmpyadd,sgl %1,%2,%0,%4,%3\"; | |
4765 | else | |
4766 | return \"fmpyadd,sgl %1,%2,%0,%5,%3\"; | |
4767 | } | |
4768 | }" | |
4769 | [(set_attr "type" "fpalu") | |
4770 | (set_attr "length" "4")]) | |
4771 | ||
4772 | (define_insn "" | |
0b27d5dd TG |
4773 | [(set (match_operand 3 "register_operand" "+f") |
4774 | (plus (match_operand 4 "register_operand" "f") | |
4775 | (match_operand 5 "register_operand" "f"))) | |
4776 | (set (match_operand 0 "register_operand" "=f") | |
4777 | (mult (match_operand 1 "register_operand" "f") | |
4778 | (match_operand 2 "register_operand" "f")))] | |
c4bb6b38 JL |
4779 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT |
4780 | && reload_completed && fmpyaddoperands (operands)" | |
2c871711 JL |
4781 | "* |
4782 | { | |
4783 | if (GET_MODE (operands[0]) == DFmode) | |
19386a3e JL |
4784 | { |
4785 | if (rtx_equal_p (operands[3], operands[5])) | |
4786 | return \"fmpyadd,dbl %1,%2,%0,%4,%3\"; | |
4787 | else | |
4788 | return \"fmpyadd,dbl %1,%2,%0,%5,%3\"; | |
4789 | } | |
2c871711 | 4790 | else |
19386a3e JL |
4791 | { |
4792 | if (rtx_equal_p (operands[3], operands[5])) | |
4793 | return \"fmpyadd,sgl %1,%2,%0,%4,%3\"; | |
4794 | else | |
4795 | return \"fmpyadd,sgl %1,%2,%0,%5,%3\"; | |
4796 | } | |
c4bb6b38 JL |
4797 | }" |
4798 | [(set_attr "type" "fpalu") | |
4799 | (set_attr "length" "4")]) | |
2c871711 | 4800 | |
c4bb6b38 | 4801 | (define_insn "" |
0b27d5dd TG |
4802 | [(set (match_operand 0 "register_operand" "=f") |
4803 | (mult (match_operand 1 "register_operand" "f") | |
4804 | (match_operand 2 "register_operand" "f"))) | |
4805 | (set (match_operand 3 "register_operand" "+f") | |
4806 | (minus (match_operand 4 "register_operand" "f") | |
4807 | (match_operand 5 "register_operand" "f")))] | |
c4bb6b38 JL |
4808 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT |
4809 | && reload_completed && fmpysuboperands (operands)" | |
2c871711 JL |
4810 | "* |
4811 | { | |
4812 | if (GET_MODE (operands[0]) == DFmode) | |
4813 | return \"fmpysub,dbl %1,%2,%0,%5,%3\"; | |
4814 | else | |
4815 | return \"fmpysub,sgl %1,%2,%0,%5,%3\"; | |
c4bb6b38 JL |
4816 | }" |
4817 | [(set_attr "type" "fpalu") | |
4818 | (set_attr "length" "4")]) | |
2c871711 | 4819 | |
c4bb6b38 | 4820 | (define_insn "" |
0b27d5dd TG |
4821 | [(set (match_operand 3 "register_operand" "+f") |
4822 | (minus (match_operand 4 "register_operand" "f") | |
4823 | (match_operand 5 "register_operand" "f"))) | |
4824 | (set (match_operand 0 "register_operand" "=f") | |
4825 | (mult (match_operand 1 "register_operand" "f") | |
4826 | (match_operand 2 "register_operand" "f")))] | |
c4bb6b38 JL |
4827 | "TARGET_SNAKE && ! TARGET_SOFT_FLOAT |
4828 | && reload_completed && fmpysuboperands (operands)" | |
2c871711 JL |
4829 | "* |
4830 | { | |
4831 | if (GET_MODE (operands[0]) == DFmode) | |
4832 | return \"fmpysub,dbl %1,%2,%0,%5,%3\"; | |
4833 | else | |
4834 | return \"fmpysub,sgl %1,%2,%0,%5,%3\"; | |
c4bb6b38 JL |
4835 | }" |
4836 | [(set_attr "type" "fpalu") | |
4837 | (set_attr "length" "4")]) | |
0002b1a8 | 4838 | |
ad238e4b JL |
4839 | ;; Clean up turds left by reload. |
4840 | (define_peephole | |
4841 | [(set (match_operand 0 "reg_or_nonsymb_mem_operand" "") | |
63e7fe9b JL |
4842 | (match_operand 1 "register_operand" "fr")) |
4843 | (set (match_operand 2 "register_operand" "fr") | |
ad238e4b JL |
4844 | (match_dup 0))] |
4845 | "! TARGET_SOFT_FLOAT | |
4846 | && GET_CODE (operands[0]) == MEM | |
4847 | && ! MEM_VOLATILE_P (operands[0]) | |
4848 | && GET_MODE (operands[0]) == GET_MODE (operands[1]) | |
4849 | && GET_MODE (operands[0]) == GET_MODE (operands[2]) | |
4850 | && GET_MODE (operands[0]) == DFmode | |
63e7fe9b JL |
4851 | && GET_CODE (operands[1]) == REG |
4852 | && GET_CODE (operands[2]) == REG | |
f0501149 | 4853 | && ! side_effects_p (XEXP (operands[0], 0)) |
ad238e4b JL |
4854 | && REGNO_REG_CLASS (REGNO (operands[1])) |
4855 | == REGNO_REG_CLASS (REGNO (operands[2]))" | |
4856 | "* | |
4857 | { | |
4858 | enum machine_mode mode = GET_MODE (operands[0]); | |
4859 | rtx xoperands[2]; | |
4860 | ||
4861 | if (FP_REG_P (operands[1])) | |
4862 | output_asm_insn (output_fp_move_double (operands), operands); | |
4863 | else | |
4864 | output_asm_insn (output_move_double (operands), operands); | |
4865 | ||
4866 | if (rtx_equal_p (operands[1], operands[2])) | |
4867 | return \"\"; | |
4868 | ||
4869 | xoperands[0] = operands[2]; | |
4870 | xoperands[1] = operands[1]; | |
4871 | ||
4872 | if (FP_REG_P (xoperands[1])) | |
4873 | output_asm_insn (output_fp_move_double (xoperands), xoperands); | |
4874 | else | |
4875 | output_asm_insn (output_move_double (xoperands), xoperands); | |
4876 | ||
4877 | return \"\"; | |
4878 | }") | |
4879 | ||
0f05dcc2 | 4880 | (define_peephole |
63e7fe9b | 4881 | [(set (match_operand 0 "register_operand" "fr") |
0f05dcc2 | 4882 | (match_operand 1 "reg_or_nonsymb_mem_operand" "")) |
63e7fe9b | 4883 | (set (match_operand 2 "register_operand" "fr") |
0f05dcc2 JL |
4884 | (match_dup 1))] |
4885 | "! TARGET_SOFT_FLOAT | |
4886 | && GET_CODE (operands[1]) == MEM | |
4887 | && ! MEM_VOLATILE_P (operands[1]) | |
4888 | && GET_MODE (operands[0]) == GET_MODE (operands[1]) | |
4889 | && GET_MODE (operands[0]) == GET_MODE (operands[2]) | |
4890 | && GET_MODE (operands[0]) == DFmode | |
63e7fe9b JL |
4891 | && GET_CODE (operands[0]) == REG |
4892 | && GET_CODE (operands[2]) == REG | |
f0501149 | 4893 | && ! side_effects_p (XEXP (operands[1], 0)) |
63e7fe9b | 4894 | && REGNO_REG_CLASS (REGNO (operands[0])) |
0f05dcc2 JL |
4895 | == REGNO_REG_CLASS (REGNO (operands[2]))" |
4896 | "* | |
4897 | { | |
4898 | enum machine_mode mode = GET_MODE (operands[0]); | |
4899 | rtx xoperands[2]; | |
4900 | ||
4901 | if (FP_REG_P (operands[0])) | |
4902 | output_asm_insn (output_fp_move_double (operands), operands); | |
4903 | else | |
4904 | output_asm_insn (output_move_double (operands), operands); | |
4905 | ||
4906 | xoperands[0] = operands[2]; | |
4907 | xoperands[1] = operands[0]; | |
4908 | ||
4909 | if (FP_REG_P (xoperands[1])) | |
4910 | output_asm_insn (output_fp_move_double (xoperands), xoperands); | |
4911 | else | |
4912 | output_asm_insn (output_move_double (xoperands), xoperands); | |
4913 | ||
4914 | return \"\"; | |
4915 | }") | |
4916 | ||
0002b1a8 JL |
4917 | ;; Flush the I and D cache line found at the address in operand 0. |
4918 | ;; This is used by the trampoline code for nested functions. | |
4919 | ;; So long as the trampoline itself is less than 32 bytes this | |
4920 | ;; is sufficient. | |
bdc87462 TG |
4921 | |
4922 | (define_insn "dcacheflush" | |
0002b1a8 | 4923 | [(unspec_volatile [(const_int 1)] 0) |
823c6f60 RS |
4924 | (use (mem:SI (match_operand:SI 0 "register_operand" "r"))) |
4925 | (use (mem:SI (match_operand:SI 1 "register_operand" "r")))] | |
0002b1a8 | 4926 | "" |
bdc87462 | 4927 | "fdc 0(0,%0)\;fdc 0(0,%1)\;sync" |
c47decad JL |
4928 | [(set_attr "type" "multi") |
4929 | (set_attr "length" "12")]) | |
bdc87462 TG |
4930 | |
4931 | (define_insn "icacheflush" | |
4932 | [(unspec_volatile [(const_int 2)] 0) | |
4933 | (use (mem:SI (match_operand:SI 0 "register_operand" "r"))) | |
4934 | (use (mem:SI (match_operand:SI 1 "register_operand" "r"))) | |
4935 | (use (match_operand:SI 2 "register_operand" "r")) | |
4936 | (clobber (match_operand:SI 3 "register_operand" "=&r")) | |
4937 | (clobber (match_operand:SI 4 "register_operand" "=&r"))] | |
4938 | "" | |
4939 | "mfsp %%sr0,%4\;ldsid (0,%2),%3\;mtsp %3,%%sr0\;fic 0(%%sr0,%0)\;fic 0(%%sr0,%1)\;sync\;mtsp %4,%%sr0\;nop\;nop\;nop\;nop\;nop\;nop" | |
c47decad JL |
4940 | [(set_attr "type" "multi") |
4941 | (set_attr "length" "52")]) | |
9e18f575 JL |
4942 | |
4943 | ;; An out-of-line prologue. | |
4944 | (define_insn "outline_prologue_call" | |
4945 | [(unspec_volatile [(const_int 0)] 0) | |
4946 | (clobber (reg:SI 31)) | |
4947 | (clobber (reg:SI 22)) | |
4948 | (clobber (reg:SI 21)) | |
4949 | (clobber (reg:SI 20)) | |
4950 | (clobber (reg:SI 19)) | |
4951 | (clobber (reg:SI 1))] | |
4952 | "" | |
4953 | "* | |
4954 | { | |
e63ffc38 | 4955 | extern int frame_pointer_needed; |
9e18f575 | 4956 | |
e63ffc38 JL |
4957 | /* We need two different versions depending on whether or not we |
4958 | need a frame pointer. Also note that we return to the instruction | |
4959 | immediately after the branch rather than two instructions after the | |
4960 | break as normally is the case. */ | |
4961 | if (frame_pointer_needed) | |
9e18f575 | 4962 | { |
e63ffc38 JL |
4963 | /* Must import the magic millicode routine(s). */ |
4964 | output_asm_insn (\".IMPORT __outline_prologue_fp,MILLICODE\", NULL); | |
4965 | ||
4966 | if (TARGET_PORTABLE_RUNTIME) | |
4967 | { | |
4968 | output_asm_insn (\"ldil L'__outline_prologue_fp,%%r31\", NULL); | |
4969 | output_asm_insn (\"ble,n R'__outline_prologue_fp(%%sr0,%%r31)\", | |
4970 | NULL); | |
4971 | } | |
4972 | else | |
4973 | output_asm_insn (\"bl,n __outline_prologue_fp,%%r31\", NULL); | |
9e18f575 JL |
4974 | } |
4975 | else | |
e63ffc38 JL |
4976 | { |
4977 | /* Must import the magic millicode routine(s). */ | |
4978 | output_asm_insn (\".IMPORT __outline_prologue,MILLICODE\", NULL); | |
4979 | ||
4980 | if (TARGET_PORTABLE_RUNTIME) | |
4981 | { | |
4982 | output_asm_insn (\"ldil L'__outline_prologue,%%r31\", NULL); | |
4983 | output_asm_insn (\"ble,n R'__outline_prologue(%%sr0,%%r31)\", NULL); | |
4984 | } | |
4985 | else | |
4986 | output_asm_insn (\"bl,n __outline_prologue,%%r31\", NULL); | |
4987 | } | |
9e18f575 JL |
4988 | return \"\"; |
4989 | }" | |
4990 | [(set_attr "type" "multi") | |
4991 | (set_attr "length" "8")]) | |
4992 | ||
4993 | ;; An out-of-line epilogue. | |
4994 | (define_insn "outline_epilogue_call" | |
4995 | [(unspec_volatile [(const_int 1)] 0) | |
4996 | (use (reg:SI 29)) | |
4997 | (use (reg:SI 28)) | |
4998 | (clobber (reg:SI 31)) | |
4999 | (clobber (reg:SI 22)) | |
5000 | (clobber (reg:SI 21)) | |
5001 | (clobber (reg:SI 20)) | |
5002 | (clobber (reg:SI 19)) | |
5003 | (clobber (reg:SI 2)) | |
5004 | (clobber (reg:SI 1))] | |
5005 | "" | |
5006 | "* | |
5007 | { | |
e63ffc38 | 5008 | extern int frame_pointer_needed; |
9e18f575 | 5009 | |
e63ffc38 JL |
5010 | /* We need two different versions depending on whether or not we |
5011 | need a frame pointer. Also note that we return to the instruction | |
5012 | immediately after the branch rather than two instructions after the | |
5013 | break as normally is the case. */ | |
5014 | if (frame_pointer_needed) | |
9e18f575 | 5015 | { |
e63ffc38 JL |
5016 | /* Must import the magic millicode routine. */ |
5017 | output_asm_insn (\".IMPORT __outline_epilogue_fp,MILLICODE\", NULL); | |
5018 | ||
5019 | /* The out-of-line prologue will make sure we return to the right | |
5020 | instruction. */ | |
5021 | if (TARGET_PORTABLE_RUNTIME) | |
5022 | { | |
5023 | output_asm_insn (\"ldil L'__outline_epilogue_fp,%%r31\", NULL); | |
5024 | output_asm_insn (\"ble,n R'__outline_epilogue_fp(%%sr0,%%r31)\", | |
5025 | NULL); | |
5026 | } | |
5027 | else | |
5028 | output_asm_insn (\"bl,n __outline_epilogue_fp,%%r31\", NULL); | |
9e18f575 JL |
5029 | } |
5030 | else | |
e63ffc38 JL |
5031 | { |
5032 | /* Must import the magic millicode routine. */ | |
5033 | output_asm_insn (\".IMPORT __outline_epilogue,MILLICODE\", NULL); | |
5034 | ||
5035 | /* The out-of-line prologue will make sure we return to the right | |
5036 | instruction. */ | |
5037 | if (TARGET_PORTABLE_RUNTIME) | |
5038 | { | |
5039 | output_asm_insn (\"ldil L'__outline_epilogue,%%r31\", NULL); | |
5040 | output_asm_insn (\"ble,n R'__outline_epilogue(%%sr0,%%r31)\", NULL); | |
5041 | } | |
5042 | else | |
5043 | output_asm_insn (\"bl,n __outline_epilogue,%%r31\", NULL); | |
5044 | } | |
9e18f575 JL |
5045 | return \"\"; |
5046 | }" | |
5047 | [(set_attr "type" "multi") | |
5048 | (set_attr "length" "8")]) | |
5049 | ||
ea06b0ed JL |
5050 | ;; Given a function pointer, canonicalize it so it can be |
5051 | ;; reliably compared to another function pointer. */ | |
5052 | (define_expand "canonicalize_funcptr_for_compare" | |
5053 | [(set (reg:SI 26) (match_operand:SI 1 "register_operand" "")) | |
5054 | (parallel [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] 0)) | |
5055 | (clobber (match_dup 2)) | |
5056 | (clobber (reg:SI 26)) | |
5057 | (clobber (reg:SI 22)) | |
5058 | (clobber (reg:SI 31))]) | |
5059 | (set (match_operand:SI 0 "register_operand" "") | |
5060 | (reg:SI 29))] | |
5061 | "! TARGET_PORTABLE_RUNTIME" | |
5062 | " | |
5063 | { | |
5064 | operands[2] = gen_reg_rtx (SImode); | |
5065 | if (GET_CODE (operands[1]) != REG) | |
458c16f7 JL |
5066 | { |
5067 | rtx tmp = gen_reg_rtx (Pmode); | |
5068 | emit_move_insn (tmp, operands[1]); | |
5069 | operands[1] = tmp; | |
5070 | } | |
ea06b0ed JL |
5071 | }") |
5072 | ||
5073 | (define_insn "" | |
b46de15e JL |
5074 | [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] 0)) |
5075 | (clobber (match_operand:SI 0 "register_operand" "=a")) | |
5076 | (clobber (reg:SI 26)) | |
5077 | (clobber (reg:SI 22)) | |
5078 | (clobber (reg:SI 31))] | |
5079 | "" | |
5080 | "* | |
5081 | { | |
5082 | /* Must import the magic millicode routine. */ | |
5083 | output_asm_insn (\".IMPORT $$sh_func_adrs,MILLICODE\", NULL); | |
5084 | ||
956d6950 | 5085 | /* This is absolutely amazing. |
b46de15e JL |
5086 | |
5087 | First, copy our input parameter into %r29 just in case we don't | |
5088 | need to call $$sh_func_adrs. */ | |
5089 | output_asm_insn (\"copy %%r26,%%r29\", NULL); | |
5090 | ||
5091 | /* Next, examine the low two bits in %r26, if they aren't 0x2, then | |
5092 | we use %r26 unchanged. */ | |
5093 | if (get_attr_length (insn) == 32) | |
5094 | output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+24\", NULL); | |
5095 | else if (get_attr_length (insn) == 40) | |
5096 | output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+32\", NULL); | |
5097 | else if (get_attr_length (insn) == 44) | |
5098 | output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+36\", NULL); | |
5099 | else | |
5100 | output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+20\", NULL); | |
5101 | ||
5102 | /* Next, compare %r26 with 4096, if %r26 is less than or equal to | |
5103 | 4096, then we use %r26 unchanged. */ | |
5104 | if (get_attr_length (insn) == 32) | |
5105 | output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+16\", NULL); | |
5106 | else if (get_attr_length (insn) == 40) | |
5107 | output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+24\", NULL); | |
5108 | else if (get_attr_length (insn) == 44) | |
5109 | output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+28\", NULL); | |
5110 | else | |
5111 | output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+12\", NULL); | |
5112 | ||
5113 | /* Else call $$sh_func_adrs to extract the function's real add24. */ | |
5114 | return output_millicode_call (insn, | |
5115 | gen_rtx (SYMBOL_REF, SImode, | |
5116 | \"$$sh_func_adrs\")); | |
5117 | }" | |
5118 | [(set_attr "type" "multi") | |
5119 | (set (attr "length") | |
5120 | (cond [ | |
5121 | ;; Target (or stub) within reach | |
5122 | (and (lt (plus (symbol_ref "total_code_bytes") (pc)) | |
5123 | (const_int 240000)) | |
5124 | (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
5125 | (const_int 0))) | |
5126 | (const_int 28) | |
5127 | ||
5128 | ;; NO_SPACE_REGS | |
3aba034b | 5129 | (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS") |
b46de15e JL |
5130 | (const_int 0)) |
5131 | (const_int 32) | |
5132 | ||
5133 | ;; Out of reach, but not PIC or PORTABLE_RUNTIME | |
5134 | ;; same as NO_SPACE_REGS code | |
5135 | (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") | |
5136 | (const_int 0)) | |
5137 | (eq (symbol_ref "flag_pic") | |
5138 | (const_int 0))) | |
5139 | (const_int 32) | |
5140 | ||
956d6950 | 5141 | ;; PORTABLE_RUNTIME |
b46de15e JL |
5142 | (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") |
5143 | (const_int 0)) | |
5144 | (const_int 40)] | |
5145 | ||
5146 | ;; Out of range and PIC | |
5147 | (const_int 44)))]) | |
5148 | ||
c133e33c MS |
5149 | ;; On the PA, the PIC register is call clobbered, so it must |
5150 | ;; be saved & restored around calls by the caller. If the call | |
5151 | ;; doesn't return normally (nonlocal goto, or an exception is | |
5152 | ;; thrown), then the code at the exception handler label must | |
5153 | ;; restore the PIC register. | |
5154 | (define_expand "exception_receiver" | |
5155 | [(const_int 4)] | |
5156 | "!TARGET_PORTABLE_RUNTIME && flag_pic" | |
5157 | " | |
5158 | { | |
5159 | /* Load the PIC register from the stack slot (in our caller's | |
5160 | frame). */ | |
5161 | emit_move_insn (pic_offset_table_rtx, | |
5162 | gen_rtx (MEM, SImode, | |
5163 | plus_constant (stack_pointer_rtx, -32))); | |
5164 | emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); | |
5165 | emit_insn (gen_blockage ()); | |
5166 | DONE; | |
5167 | }") | |
5168 | ||
b46de15e | 5169 |