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