]>
Commit | Line | Data |
---|---|---|
7acf4da6 | 1 | ;; Toshiba Media Processor Machine description template |
23a5b65a | 2 | ;; Copyright (C) 2001-2014 Free Software Foundation, Inc. |
7acf4da6 DD |
3 | ;; Contributed by Red Hat Inc |
4 | ;; | |
5 | ;; This file is part of GCC. | |
6 | ;; | |
7 | ;; GCC is free software; you can redistribute it and/or modify it | |
8 | ;; under the terms of the GNU General Public License as published by | |
9 | ;; the Free Software Foundation; either version 3, or (at your option) | |
10 | ;; any later version. | |
11 | ;; | |
12 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT | |
13 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | ;; License for more details. | |
16 | ;; | |
17 | ;; You should have received a copy of the GNU General Public License | |
18 | ;; along with GCC; see the file COPYING3. If not see | |
19 | ;; <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | \f | |
22 | ||
23 | ;; Constraints: | |
24 | ;; | |
25 | ;; a $sp | |
26 | ;; b $tp | |
27 | ;; c control regs | |
28 | ;; h $hi ($23) | |
29 | ;; l $lo ($24) | |
30 | ;; d $hi/$lo pair (DImode) | |
31 | ;; j $rpc ($22) | |
32 | ;; r $0..$15 | |
33 | ;; t $0..$7 | |
34 | ;; v $gp | |
35 | ;; x $c0..$c31 | |
36 | ;; ex coprocessor registers that can be moved to other coprocessor registers | |
37 | ;; er coprocessor registers that can be moved to and from core registers | |
38 | ;; em coprocessor registers that can be moves to and from memory | |
39 | ;; y $ccr0..$ccr31 | |
40 | ;; z $0 | |
41 | ;; | |
42 | ;; I sign imm16 mov/add | |
43 | ;; J zero imm16 mov/add | |
44 | ;; K zero imm24 mov | |
45 | ;; L sign imm6 add | |
46 | ;; M zero imm5 slt,shifts | |
47 | ;; N zero imm4 bCC | |
48 | ;; O high imm16 mov | |
49 | ;; | |
50 | ;; R near symbol | |
51 | ;; S sign imm8 mov | |
52 | ;; T tp or gp relative symbol | |
53 | ;; U non-absolute memory | |
54 | ;; W %hi(sym) | |
55 | ;; Y (Rn) | |
56 | ;; Z Control Bus Symbol | |
57 | ;; | |
58 | ;; Modifiers: | |
59 | ;; | |
60 | ;; b print unique bit in mask | |
61 | ;; B print bits required for value (for clip) | |
62 | ;; h print decimal >> 16. | |
63 | ;; I print decimal, with hex comment if more than 8 bits | |
64 | ;; J print unsigned hex | |
65 | ;; L print set, clr or not (for bitops) | |
66 | ;; P print memory as a post-inc with no increment | |
67 | ;; U print bits required for value (for clipu) | |
68 | ;; x print unsigned decimal or hex, depending on where set bits are | |
69 | ||
70 | (define_constants [ | |
71 | (REGSAVE_CONTROL_TEMP 11) | |
72 | (FP_REGNO 8) | |
73 | (TP_REGNO 13) | |
74 | (GP_REGNO 14) | |
75 | (SP_REGNO 15) | |
76 | (PSW_REGNO 16) | |
77 | (LP_REGNO 17) | |
78 | (SAR_REGNO 18) | |
79 | (RPB_REGNO 20) | |
80 | (RPE_REGNO 21) | |
81 | (RPC_REGNO 22) | |
82 | (HI_REGNO 23) | |
83 | (LO_REGNO 24) | |
84 | (CBCR_REGNO 81) | |
85 | ]) | |
86 | ||
87 | (define_constants [ | |
88 | (UNS_BLOCKAGE 0) | |
89 | (UNS_TPREL 2) | |
90 | (UNS_GPREL 3) | |
91 | (UNS_REPEAT_BEG 4) | |
92 | (UNS_REPEAT_END 5) | |
93 | (UNS_EH_EPILOGUE 6) | |
94 | (UNS_EREPEAT_BEG 7) | |
95 | (UNS_EREPEAT_END 8) | |
96 | (UNS_BB_TRACE_RET 9) | |
97 | (UNS_DISABLE_INT 10) | |
98 | (UNS_ENABLE_INT 11) | |
99 | (UNS_RETI 12) | |
100 | ]) | |
101 | \f | |
102 | ;; This attribute determines the VLIW packing mechanism. The IVC2 | |
103 | ;; coprocessor has two pipelines (P0 and P1), and a MeP+IVC2 can issue | |
104 | ;; up to three insns at a time. Most IVC2 insns can run on either | |
105 | ;; pipeline, however, scheduling some insns on P0 precludes packing a | |
106 | ;; core insn with it, and only 16-bit core insns can pack with any P0 | |
107 | ;; insn. | |
108 | (define_attr "vliw" "basic,ivc2" | |
109 | (const (symbol_ref "TARGET_IVC2"))) | |
110 | ||
111 | ;; This attribute describes the kind of memory operand present in the | |
112 | ;; instruction. This is used to compute the length of the insn based | |
113 | ;; on the addressing mode used. | |
114 | (define_attr "memop" "none,core0,core1,cop0,cop1" | |
115 | (const_string "none")) | |
116 | ||
117 | (define_attr "intrinsic" "none,cmov,cmov1,cmov2,cmovc1,cmovc2,cmovh1,cmovh2" | |
118 | (const_string "none")) | |
119 | ||
120 | ;; This attribute describes how the instruction may be bundled in a | |
121 | ;; VLIW instruction. Type MULTI is assumed to use both slots. | |
122 | (define_attr "slot" "core,cop,multi" | |
123 | (cond [(eq_attr "intrinsic" "!none") | |
124 | (const_string "cop")] | |
125 | (const_string "core"))) | |
126 | ||
127 | ;; This attribute describes the latency of the opcode (ready delay). | |
128 | ;; The 0 is used to indicate "unspecified". An instruction that | |
129 | ;; completes immediately with no potential stalls would have a value | |
130 | ;; of 1, a one cycle stall would be 2, etc. | |
131 | (define_attr "latency" "" | |
132 | (const_int 0)) | |
133 | ||
134 | (define_attr "shiftop" "none,operand2" | |
135 | (const_string "none")) | |
136 | ||
137 | ;; This attribute describes the size of the instruction in bytes. | |
138 | ;; This *must* be exact unless the pattern is SLOT_MULTI, as this | |
139 | ;; is used by the VLIW bundling code. | |
140 | (define_attr "length" "" | |
141 | (cond [(eq_attr "memop" "core0") | |
142 | (symbol_ref "mep_core_address_length (insn, 0)") | |
143 | (eq_attr "memop" "core1") | |
144 | (symbol_ref "mep_core_address_length (insn, 1)") | |
145 | (eq_attr "memop" "cop0") | |
146 | (symbol_ref "mep_cop_address_length (insn, 0)") | |
147 | (eq_attr "memop" "cop1") | |
148 | (symbol_ref "mep_cop_address_length (insn, 1)") | |
149 | ] | |
150 | ; Catch patterns that don't define the length properly. | |
151 | (symbol_ref "(abort (), 0)"))) | |
152 | ||
153 | ;; This attribute describes a pipeline hazard seen in the insn. | |
154 | (define_attr "stall" "none,int2,ssarb,load,store,ldc,stc,ldcb,stcb,ssrab,fsft,ret,advck,mul,mulr,div" | |
155 | (cond [(and (eq_attr "shiftop" "operand2") | |
156 | (not (match_operand:SI 2 "mep_single_shift_operand" ""))) | |
157 | (const_string "int2")] | |
158 | (const_string "none"))) | |
159 | ||
160 | (define_attr "may_trap" "no,yes" | |
161 | (const_string "no")) | |
162 | ||
163 | ;; Describe a user's asm statement. | |
164 | (define_asm_attributes | |
165 | [(set_attr "length" "4") | |
166 | (set_attr "slot" "multi")]) | |
167 | ||
168 | ;; Each IVC2 instruction uses one of these two pipelines. P0S insns | |
169 | ;; use P0; C3 insns use P1. | |
170 | (define_automaton "mep_ivc2") | |
171 | (define_cpu_unit "ivc2_core,ivc2_p0,ivc2_p1" "mep_ivc2") | |
172 | ||
173 | ;; Each core or IVC2 instruction is bundled into one of these slots. | |
174 | ;; Supported bundlings: | |
175 | ;; | |
176 | ;; Core mode: | |
177 | ;; | |
178 | ;; C1 [-----core-----] | |
179 | ;; C2 [-------------core-------------] | |
180 | ;; C3 [--------------c3--------------] | |
181 | ;; | |
182 | ;; VLIW mode: | |
183 | ;; | |
184 | ;; V1 [-----core-----][--------p0s-------][------------p1------------] | |
185 | ;; V2 [-------------core-------------]xxxx[------------p1------------] | |
186 | ;; V3 1111[--p0--]0111[--------p0--------][------------p1------------] | |
187 | ||
188 | (define_attr "slots" "core,c3,p0,p0_p0s,p0_p1,p0s,p0s_p1,p1" (const_string "core")) | |
189 | ||
190 | (define_cpu_unit "ivc2_slot_c16,ivc2_slot_c32,ivc2_slot_c3,ivc2_slot_p0s,ivc2_slot_p0,ivc2_slot_p1" "mep_ivc2") | |
191 | ||
192 | (define_insn_reservation "ivc2_insn_core16" 1 | |
193 | (and (eq_attr "vliw" "ivc2") | |
194 | (and (eq (symbol_ref "get_attr_length(insn)") (const_int 2)) | |
195 | (and (eq_attr "intrinsic" "none") | |
196 | (eq_attr "slot" "!cop")))) | |
197 | "ivc2_core+ivc2_slot_c16") | |
198 | ||
199 | (define_insn_reservation "ivc2_insn_core32" 1 | |
200 | (and (eq_attr "vliw" "ivc2") | |
201 | (and (eq (symbol_ref "get_attr_length(insn)") (const_int 4)) | |
202 | (and (eq_attr "intrinsic" "none") | |
203 | (eq_attr "slot" "!cop")))) | |
204 | "ivc2_core+ivc2_slot_c32") | |
205 | ||
206 | ;; These shouldn't happen when in VLIW mode. | |
207 | (define_insn_reservation "ivc2_insn_c3" 1 | |
208 | (and (eq_attr "vliw" "ivc2") | |
209 | (eq_attr "slots" "c3")) | |
210 | "ivc2_p1+ivc2_slot_c3") | |
211 | ||
212 | (define_insn_reservation "ivc2_insn_p0" 1 | |
213 | (and (eq_attr "vliw" "ivc2") | |
214 | (eq_attr "slots" "p0")) | |
215 | "ivc2_p0+ivc2_slot_p0") | |
216 | ||
217 | (define_insn_reservation "ivc2_insn_p0_p0s" 1 | |
218 | (and (eq_attr "vliw" "ivc2") | |
219 | (eq_attr "slots" "p0_p0s")) | |
220 | "ivc2_p0+ivc2_slot_p0|ivc2_p0+ivc2_slot_p0s") | |
221 | ||
222 | (define_insn_reservation "ivc2_insn_p0_p1" 1 | |
223 | (and (eq_attr "vliw" "ivc2") | |
224 | (eq_attr "slots" "p0_p1")) | |
225 | "ivc2_p0+ivc2_slot_p0|ivc2_p1+ivc2_slot_p1") | |
226 | ||
227 | (define_insn_reservation "ivc2_insn_p0s" 1 | |
228 | (and (eq_attr "vliw" "ivc2") | |
229 | (eq_attr "slots" "p0s")) | |
230 | "ivc2_p0+ivc2_slot_p0s") | |
231 | ||
232 | (define_insn_reservation "ivc2_insn_p0s_p1" 1 | |
233 | (and (eq_attr "vliw" "ivc2") | |
234 | (eq_attr "slots" "p0s_p1")) | |
235 | "ivc2_p0+ivc2_slot_p0s|ivc2_p1+ivc2_slot_p1") | |
236 | ||
237 | (define_insn_reservation "ivc2_insn_p1" 1 | |
238 | (and (eq_attr "vliw" "ivc2") | |
239 | (eq_attr "slots" "p1")) | |
240 | "ivc2_p1+ivc2_slot_p1") | |
241 | ||
242 | ;; these run in C3 also, but when we're doing VLIW scheduling, they | |
243 | ;; only run in P0. | |
244 | (define_insn_reservation "ivc2_insn_cmov" 1 | |
245 | (and (eq_attr "vliw" "ivc2") | |
246 | (eq_attr "intrinsic" "!none")) | |
247 | "ivc2_p0+ivc2_slot_p0") | |
248 | ||
249 | ||
250 | (exclusion_set "ivc2_slot_c32" | |
251 | "ivc2_slot_p0,ivc2_slot_p0s") | |
252 | (exclusion_set "ivc2_slot_p0" | |
253 | "ivc2_slot_p0s") | |
254 | (exclusion_set "ivc2_slot_c16" | |
255 | "ivc2_slot_p0") | |
256 | (exclusion_set "ivc2_slot_c16" | |
257 | "ivc2_slot_c32") | |
258 | ||
259 | ;; Non-IVC2 scheduling. | |
260 | (define_automaton "mep") | |
261 | (define_cpu_unit "core,cop" "mep") | |
262 | ||
263 | ;; Latencies are the time between one insn entering the second pipeline | |
264 | ;; stage (E2, LD, A2 or V2) and the next instruction entering the same | |
265 | ;; stage. When an instruction assigns to general registers, the default | |
266 | ;; latencies are for when the next instruction receives the register | |
267 | ;; through bypass 1. | |
268 | ||
269 | ;; Arithmetic instructions that execute in a single stage. | |
270 | (define_insn_reservation "h1_int1" 2 | |
271 | (and (eq_attr "slot" "!cop") | |
272 | (eq_attr "stall" "none")) | |
273 | "core") | |
274 | (define_bypass 1 "h1_int1" "h1_int1,h1_ssarb") | |
275 | (define_bypass 1 "h1_int1" "h1_store" "mep_store_data_bypass_p") | |
276 | ||
277 | ;; $sar can be read by an immediately following fsft or ldc. | |
278 | (define_insn_reservation "h1_ssarb" 1 | |
279 | (eq_attr "stall" "ssarb") | |
280 | "core") | |
281 | ||
282 | ;; Arithmetic instructions that execute in two stages. | |
283 | (define_insn_reservation "h1_int2" 2 | |
284 | (eq_attr "stall" "int2,fsft") | |
285 | "core") | |
286 | (define_bypass 1 "h1_int2" "h1_int1,h1_ssarb") | |
287 | (define_bypass 1 "h1_int2" "h1_store" "mep_store_data_bypass_p") | |
288 | ||
289 | (define_insn_reservation "h1_load" 4 | |
290 | (eq_attr "stall" "load") | |
291 | "core") | |
292 | (define_bypass 3 "h1_load" "h1_int1,h1_ssarb") | |
293 | (define_bypass 3 "h1_load" "h1_store" "mep_store_data_bypass_p") | |
294 | ||
295 | (define_insn_reservation "h1_store" 1 | |
296 | (eq_attr "stall" "store") | |
297 | "core") | |
298 | ||
299 | (define_insn_reservation "h1_ipipe_ldc" 2 | |
300 | (and (eq_attr "stall" "ldc") | |
301 | (ne (symbol_ref "mep_ipipe_ldc_p(insn)") (const_int 0))) | |
302 | "core") | |
303 | (define_bypass 1 "h1_ipipe_ldc" "h1_int1,h1_ssarb") | |
304 | (define_bypass 1 "h1_ipipe_ldc" "h1_store" "mep_store_data_bypass_p") | |
305 | ||
306 | (define_insn_reservation "h1_apipe_ldc" 2 | |
307 | (and (eq_attr "stall" "ldc") | |
308 | (eq (symbol_ref "mep_ipipe_ldc_p(insn)") (const_int 0))) | |
309 | "core") | |
310 | ||
311 | ;; 2 is correct for stc->ret and stc->fsft. The most important remaining | |
312 | ;; case is stc->madd, which induces no stall. | |
313 | (define_insn_reservation "h1_stc" 2 | |
314 | (eq_attr "stall" "stc") | |
315 | "core") | |
316 | (define_bypass 1 "h1_stc" "h1_mul") | |
317 | ||
318 | ;; ??? Parameterised latency. | |
319 | (define_insn_reservation "h1_ldcb" 5 | |
320 | (eq_attr "stall" "ldcb") | |
321 | "core") | |
322 | ||
323 | (define_insn_reservation "h1_stcb" 1 | |
324 | (eq_attr "stall" "stcb") | |
325 | "core") | |
326 | ||
327 | (define_insn_reservation "h1_advck" 6 | |
328 | (eq_attr "stall" "advck") | |
329 | "core") | |
330 | ||
331 | (define_insn_reservation "h1_mul" 5 | |
332 | (eq_attr "stall" "mul,mulr") | |
333 | "core") | |
334 | (define_bypass 4 "h1_mul" "h1_int1,h1_ssarb") | |
335 | (define_bypass 4 "h1_mul" "h1_store" "mep_store_data_bypass_p") | |
336 | (define_bypass 1 "h1_mul" "h1_mul" "mep_mul_hilo_bypass_p") | |
337 | ||
338 | (define_insn_reservation "h1_div" 36 | |
339 | (eq_attr "stall" "div") | |
340 | "core") | |
341 | ||
342 | (define_insn_reservation "h1_cop" 1 | |
343 | (eq_attr "slot" "cop") | |
344 | "cop") | |
345 | \f | |
346 | (include "predicates.md") | |
347 | (include "constraints.md") | |
348 | (include "intrinsics.md") | |
349 | \f | |
350 | ;; :::::::::::::::::::: | |
351 | ;; :: | |
352 | ;; :: Moves | |
353 | ;; :: | |
354 | ;; :::::::::::::::::::: | |
355 | ||
356 | (define_expand "movqi" | |
357 | [(set (match_operand:QI 0 "general_operand" "") | |
358 | (match_operand:QI 1 "general_operand" ""))] | |
359 | "" | |
360 | " | |
361 | { | |
362 | if (mep_expand_mov (operands, QImode)) | |
363 | DONE; | |
364 | }") | |
365 | ||
366 | ;; The Idea here is to prefer the 16-bit tp-relative load, but to fall back | |
367 | ;; to the general 32-bit load rather than do silly things with spill regs. | |
368 | (define_insn "*movqi_tprel_load" | |
369 | [(set (match_operand:QI 0 "mep_tprel_operand" "=t,*r") | |
370 | (mem:QI (plus:SI (match_operand:SI 1 "mep_tp_operand" "b,*r") | |
371 | (const:SI (unspec:SI [(match_operand:SI 2 | |
372 | "symbolic_operand" "s,s")] | |
373 | UNS_TPREL)))))] | |
374 | "" | |
375 | "lb\\t%0, %%tpoff(%2)(%1)" | |
376 | [(set_attr "length" "2,4") | |
377 | (set_attr "stall" "load")]) | |
378 | ||
379 | (define_insn "*movqi_tprel_store" | |
380 | [(set (mem:QI (plus:SI (match_operand:SI 0 "mep_tp_operand" "b,*r") | |
381 | (const:SI (unspec:SI [(match_operand:SI 1 | |
382 | "symbolic_operand" "s,s")] | |
383 | UNS_TPREL)))) | |
384 | (match_operand:QI 2 "mep_tprel_operand" "t,*r"))] | |
385 | "" | |
386 | "sb\\t%2, %%tpoff(%1)(%0)" | |
387 | [(set_attr "length" "2,4") | |
388 | (set_attr "stall" "store")]) | |
389 | ||
390 | (define_insn "*movqi_internal" | |
391 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r, r,m,r,c,r,y,r,er,ex,em,Y") | |
392 | (match_operand:QI 1 "general_operand" " r,n,rm,r,c,r,y,r,er,r,ex,Y,em"))] | |
393 | "mep_mov_ok (operands, QImode)" | |
394 | "@ | |
395 | mov\\t%0, %1 | |
396 | mov\\t%0, %1 | |
397 | lb\\t%0, %1 | |
398 | sb\\t%1, %0 | |
399 | ldc\\t%0, %1 | |
400 | stc\\t%1, %0 | |
401 | cmovc\\t%0, %1 | |
402 | cmovc\\t%0, %1 | |
403 | cmov\\t%0, %1 | |
404 | cmov\\t%0, %1 | |
405 | %<\\t%0, %M1 | |
406 | lbcpa\\t%0, %P1 | |
407 | sbcpa\\t%1, %P0" | |
408 | [(set_attr "length" "2,2,*,*,2,2,4,4,4,4,*,4,4") | |
409 | (set_attr "intrinsic" "*,*,*,*,*,*,cmovc2,cmovc1,cmov2,cmov1,cmov,*,*") | |
410 | (set_attr "stall" "*,*,load,store,ldc,stc,*,*,*,*,*,load,store") | |
411 | (set_attr "memop" "*,*,core1,core0,*,*,*,*,*,*,*,*,*")]) | |
412 | ||
413 | (define_expand "movhi" | |
414 | [(set (match_operand:HI 0 "general_operand" "") | |
415 | (match_operand:HI 1 "general_operand" ""))] | |
416 | "" | |
417 | " | |
418 | { | |
419 | if (mep_expand_mov (operands, HImode)) | |
420 | DONE; | |
421 | }") | |
422 | ||
423 | (define_insn "*movhi_tprel_load" | |
424 | [(set (match_operand:HI 0 "mep_tprel_operand" "=t,*r") | |
425 | (mem:HI (plus:SI (match_operand:SI 1 "mep_tp_operand" "b,*r") | |
426 | (const:SI (unspec:SI [(match_operand:SI 2 | |
427 | "symbolic_operand" "s,s")] | |
428 | UNS_TPREL)))))] | |
429 | "" | |
430 | "lh\\t%0, %%tpoff(%2)(%1)" | |
431 | [(set_attr "length" "2,4") | |
432 | (set_attr "stall" "load")]) | |
433 | ||
434 | (define_insn "*movhi_tprel_store" | |
435 | [(set (mem:HI (plus:SI (match_operand:SI 0 "mep_tp_operand" "b,*r") | |
436 | (const:SI (unspec:SI [(match_operand:SI 1 | |
437 | "symbolic_operand" "s,s")] | |
438 | UNS_TPREL)))) | |
439 | (match_operand:HI 2 "mep_tprel_operand" "t,*r"))] | |
440 | "" | |
441 | "sh\\t%2, %%tpoff(%1)(%0)" | |
442 | [(set_attr "length" "2,4") | |
443 | (set_attr "stall" "store")]) | |
444 | ||
445 | (define_insn "*movhi_internal" | |
446 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,m,r,c,r,y,r,er,ex,em,Y") | |
447 | (match_operand:HI 1 "general_operand" " r,S,n,m,r,c,r,y,r,er,r,ex,Y,em"))] | |
448 | "mep_mov_ok (operands, HImode)" | |
449 | "@ | |
450 | mov\\t%0, %1 | |
451 | mov\\t%0, %I1 | |
452 | mov\\t%0, %I1 | |
453 | lh\\t%0, %1 | |
454 | sh\\t%1, %0 | |
455 | ldc\\t%0, %1 | |
456 | stc\\t%1, %0 | |
457 | cmovc\\t%0, %1 | |
458 | cmovc\\t%0, %1 | |
459 | cmov\\t%0, %1 | |
460 | cmov\\t%0, %1 | |
461 | %<\\t%0, %M1 | |
462 | lhcpa\\t%0, %P1 | |
463 | shcpa\\t%1, %P0" | |
464 | [(set_attr "length" "2,2,4,*,*,2,2,4,4,4,4,*,4,4") | |
465 | (set_attr "intrinsic" "*,*,*,*,*,*,*,cmovc2,cmovc1,cmov2,cmov1,cmov,*,*") | |
466 | (set_attr "stall" "*,*,*,load,store,ldc,stc,*,*,*,*,*,load,store") | |
467 | (set_attr "memop" "*,*,*,core1,core0,*,*,*,*,*,*,*,*,*")]) | |
468 | ||
469 | (define_expand "movsi" | |
470 | [(set (match_operand:SI 0 "nonimmediate_operand" "") | |
471 | (match_operand:SI 1 "general_operand" ""))] | |
472 | "" | |
473 | " | |
474 | { | |
475 | if (mep_expand_mov (operands, SImode)) | |
476 | DONE; | |
477 | }") | |
478 | ||
479 | (define_insn "*movsi_tprel_load" | |
480 | [(set (match_operand:SI 0 "mep_tprel_operand" "=t,*r") | |
481 | (mem:SI (plus:SI (match_operand:SI 1 "mep_tp_operand" "b,*r") | |
482 | (const:SI (unspec:SI [(match_operand:SI 2 | |
483 | "symbolic_operand" "s,s")] | |
484 | UNS_TPREL)))))] | |
485 | "" | |
486 | "lw\\t%0, %%tpoff(%2)(%1)" | |
487 | [(set_attr "length" "2,4") | |
488 | (set_attr "stall" "load")]) | |
489 | ||
490 | (define_insn "*movsi_tprel_store" | |
491 | [(set (mem:SI (plus:SI (match_operand:SI 0 "mep_tp_operand" "b,*r") | |
492 | (const:SI (unspec:SI [(match_operand:SI 1 | |
493 | "symbolic_operand" "s,s")] | |
494 | UNS_TPREL)))) | |
495 | (match_operand:SI 2 "mep_tprel_operand" "t,*r"))] | |
496 | "" | |
497 | "sw\\t%2, %%tpoff(%1)(%0)" | |
498 | [(set_attr "length" "2,4") | |
499 | (set_attr "stall" "store")]) | |
500 | ||
501 | (define_insn "movsi_topsym_s" | |
502 | [(set (match_operand:SI 0 "register_operand" "=r") | |
503 | (high:SI (match_operand:SI 1 "symbolic_operand" "s")))] | |
504 | "" | |
505 | "movh\\t%0, %%hi(%1)" | |
506 | [(set_attr "length" "4")]) | |
507 | ||
508 | (define_insn "movsi_botsym_s" | |
509 | [(set (match_operand:SI 0 "register_operand" "=r") | |
510 | (lo_sum:SI (match_operand:SI 1 "register_operand" "0") | |
511 | (match_operand:SI 2 "symbolic_operand" "s")))] | |
512 | "" | |
513 | "add3\\t%0, %1, %%lo(%2)" | |
514 | [(set_attr "length" "4")]) | |
515 | ||
516 | ||
517 | ||
518 | (define_insn "cmovh_getsub" | |
519 | [(set (match_operand:SI 0 "register_operand" "=r") | |
520 | (subreg:SI (match_operand:DI 1 "register_operand" "er") 4))] | |
521 | "0 && TARGET_64BIT_CR_REGS" | |
522 | "cmovh\\t%0, %1" | |
523 | [(set_attr "intrinsic" "cmovh2") | |
524 | (set_attr "length" "4")]) | |
525 | ||
526 | (define_insn "*movsi_internal" | |
527 | [(set (match_operand:SI 0 "mep_movdest_operand" | |
528 | "=r,r,r,r,r, t,t,r,r,r,Z,m,r,c,r,y,r, er,ex,em,U ") | |
529 | (match_operand:SI 1 "general_operand" | |
530 | " r,S,I,J,OW,K,s,i,Z,m,r,r,c,r,y,r,er,r, ex,U, em"))] | |
531 | "mep_mov_ok (operands, SImode)" | |
532 | "@ | |
533 | mov\\t%0, %1 | |
534 | mov\\t%0, %I1 | |
535 | mov\\t%0, %I1 | |
536 | movu\\t%0, %J1 | |
537 | movh\\t%0, %h1 | |
538 | movu\\t%0, %x1 | |
539 | movu\\t%0, %1 | |
540 | # | |
541 | ldcb\\t%0, %1 | |
542 | lw\\t%0, %1 | |
543 | stcb\\t%1, %0 | |
544 | sw\\t%1, %0 | |
545 | ldc\\t%0, %1 | |
546 | stc\\t%1, %0 | |
547 | cmovc\\t%0, %1 | |
548 | cmovc\\t%0, %1 | |
549 | cmov\\t%0, %1 | |
550 | cmov\\t%0, %1 | |
551 | %<\\t%0, %M1 | |
552 | lwcp\\t%0, %1 | |
553 | swcp\\t%1, %0" | |
554 | [(set_attr "length" "2,2,4,4,4,4,4,*,4,*,4,*,2,2,4,4,4,4,4,*,*") | |
555 | (set_attr "intrinsic" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,cmovc2,cmovc1,cmov2,cmov1,cmov,*,*") | |
556 | (set_attr "stall" "*,*,*,*,*,*,*,*,ldcb,load,stcb,store,ldc,stc,*,*,*,*,*,load,store") | |
557 | (set_attr "memop" "*,*,*,*,*,*,*,*,*,core1,*,core0,*,*,*,*,*,*,*,cop1,cop0") | |
558 | (set_attr "slot" "*,*,*,*,*,*,*,multi,*,*,*,*,*,*,*,*,*,*,*,*,*")]) | |
559 | ||
560 | (define_split | |
561 | [(set (match_operand:SI 0 "register_operand" "") | |
562 | (match_operand:SI 1 "const_int_operand" ""))] | |
563 | "mep_split_mov (operands, 0)" | |
564 | [(set (match_dup 0) (match_dup 2)) | |
565 | (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))] | |
566 | " | |
567 | { | |
568 | HOST_WIDE_INT value; | |
569 | int lo, hi; | |
570 | ||
571 | value = INTVAL (operands[1]); | |
572 | ||
573 | lo = value & 0xffff; | |
574 | hi = trunc_int_for_mode (value & 0xffff0000, SImode); | |
575 | ||
576 | operands[2] = GEN_INT (hi); | |
577 | operands[3] = GEN_INT (lo); | |
578 | }") | |
579 | ||
580 | (define_split | |
581 | [(set (match_operand:SI 0 "register_operand" "") | |
582 | (match_operand:SI 1 "immediate_operand" ""))] | |
583 | "mep_split_mov (operands, 1)" | |
584 | [(set (match_dup 0) (high:SI (match_dup 1))) | |
585 | (set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 1)))] | |
586 | "") | |
587 | ||
588 | ;; ??? What purpose do these two serve that high+lo_sum do not? | |
589 | (define_insn "movsi_topsym_u" | |
590 | [(set (match_operand:SI 0 "register_operand" "=r") | |
591 | (and:SI (match_operand:SI 1 "symbolic_operand" "s") | |
592 | (const_int -65536)))] | |
593 | "" | |
594 | "movh\\t%0, %%uhi(%1)" | |
595 | [(set_attr "length" "4")]) | |
596 | ||
597 | (define_insn "movsi_botsym_u" | |
598 | [(set (match_operand:SI 0 "register_operand" "=r") | |
599 | (ior:SI (match_operand:SI 1 "register_operand" "0") | |
600 | (and:SI (match_operand:SI 2 "symbolic_operand" "s") | |
601 | (const_int 65535))))] | |
602 | "" | |
603 | "or3\\t%0, %1, %%lo(%2)" | |
604 | [(set_attr "length" "4")]) | |
605 | ||
606 | (define_expand "movdi" | |
607 | [(set (match_operand:DI 0 "" "") | |
608 | (match_operand:DI 1 "" ""))] | |
609 | "" | |
610 | " | |
611 | { | |
612 | if (mep_expand_mov (operands, DImode)) | |
613 | DONE; | |
614 | }") | |
615 | ||
616 | (define_insn "*movdi_internal_32" | |
617 | [(set (match_operand:DI 0 "mep_movdest_operand" "= r,m,r,c,r,er,ex,em,U") | |
618 | (match_operand:DI 1 "general_operand" "rim,r,c,r,er,r,ex,U,em"))] | |
619 | "TARGET_32BIT_CR_REGS && mep_mov_ok (operands, DImode)" | |
620 | "#" | |
621 | [(set_attr "slot" "multi")]) | |
622 | ||
623 | (define_insn "*movdi_internal_64" | |
624 | [(set (match_operand:DI 0 "mep_movdest_operand" "=r,r,m,r,c,r,er,ex,em,U") | |
625 | (match_operand:DI 1 "general_operand" "r,im,r,c,r,er,r,ex,U,em"))] | |
626 | "TARGET_64BIT_CR_REGS && mep_mov_ok (operands, DImode)" | |
627 | "@ | |
628 | # | |
629 | # | |
630 | # | |
631 | # | |
632 | # | |
633 | # | |
634 | # | |
635 | %<\\t%0, %M1 | |
636 | lmcp\\t%0, %1 | |
637 | smcp\\t%1, %0" | |
638 | [(set_attr "slot" "multi,multi,multi,multi,multi,multi,multi,*,*,*") | |
639 | (set_attr "intrinsic" "*,*,*,*,*,*,*,cmov,*,*") | |
640 | (set_attr "memop" "*,*,*,*,*,*,*,cop0,cop1,cop0") | |
641 | (set_attr "stall" "*,*,*,*,*,*,*,*,load,store")]) | |
642 | ||
643 | (define_insn "*movdi_cop_postinc" | |
644 | [(parallel [(set (match_operand:DI 0 "register_operand" "=em") | |
645 | (mem:DI (reg:SI SP_REGNO))) | |
646 | (set (reg:SI SP_REGNO) | |
647 | (plus:SI (reg:SI SP_REGNO) | |
648 | (const_int 8))) | |
649 | ] | |
650 | )] | |
651 | "TARGET_COP" | |
652 | "lmcpi\\t%0,($sp+)" | |
653 | [(set_attr "length" "2")]) | |
654 | ||
655 | (define_insn "*movdi_cop_postinc" | |
656 | [(parallel [(set (match_operand:DI 0 "register_operand" "=em") | |
657 | (mem:DI (match_operand:SI 2 "register_operand" "r"))) | |
658 | (set (match_operand:SI 1 "register_operand" "=0") | |
659 | (plus:SI (match_operand:SI 3 "register_operand" "0") | |
660 | (const_int 8))) | |
661 | ] | |
662 | )] | |
663 | "TARGET_COP" | |
664 | "lmcpi\\t%0,(%1+)" | |
665 | [(set_attr "length" "2")]) | |
666 | ||
667 | (define_insn "*cmovh_set" | |
668 | [(set (zero_extract:SI (match_operand:DI 0 "register_operand" "+er") | |
669 | (const_int 32) | |
670 | (const_int 32)) | |
671 | (match_operand:SI 1 "register_operand" "r"))] | |
672 | "TARGET_64BIT_CR_REGS" | |
673 | "cmovh\\t%0, %1" | |
674 | [(set_attr "intrinsic" "cmovh1") | |
675 | (set_attr "length" "4")]) | |
676 | ||
677 | (define_insn "cmovh_get" | |
678 | [(set (match_operand:SI 0 "register_operand" "=r") | |
679 | (zero_extract:SI (match_operand:DI 1 "register_operand" "er") | |
680 | (const_int 32) | |
681 | (const_int 32)))] | |
682 | "TARGET_64BIT_CR_REGS" | |
683 | "cmovh\\t%0, %1" | |
684 | [(set_attr "intrinsic" "cmovh2") | |
685 | (set_attr "length" "4")]) | |
686 | ||
687 | (define_split | |
688 | [(set (match_operand:DI 0 "mep_movdest_operand" "") | |
689 | (match_operand:DI 1 "general_operand" ""))] | |
690 | "reload_completed && mep_multi_slot (insn)" | |
691 | [(set (match_dup 2) (match_dup 3)) | |
692 | (set (match_dup 4) (match_dup 5))] | |
693 | "mep_split_wide_move (operands, DImode);") | |
694 | ||
695 | ;; Floating Point Moves | |
696 | ||
697 | (define_expand "movsf" | |
698 | [(set (match_operand:SF 0 "nonimmediate_operand" "") | |
699 | (match_operand:SF 1 "general_operand" ""))] | |
700 | "" | |
701 | " | |
702 | { | |
703 | if (mep_expand_mov (operands, SFmode)) | |
704 | DONE; | |
705 | }") | |
706 | ||
707 | (define_insn "*movsf_tprel_load" | |
708 | [(set (match_operand:SF 0 "mep_tprel_operand" "=t,*r") | |
709 | (mem:SF (plus:SI (match_operand:SI 1 "mep_tp_operand" "b,*r") | |
710 | (const:SI (unspec:SI [(match_operand:SI 2 | |
711 | "symbolic_operand" "s,s")] | |
712 | UNS_TPREL)))))] | |
713 | "" | |
714 | "lw\\t%0, %%tpoff(%2)(%1)" | |
715 | [(set_attr "length" "2,4") | |
716 | (set_attr "stall" "load")]) | |
717 | ||
718 | (define_insn "*movsf_tprel_store" | |
719 | [(set (mem:SF (plus:SI (match_operand:SI 0 "mep_tp_operand" "b,*r") | |
720 | (const:SI (unspec:SI [(match_operand:SI 1 | |
721 | "symbolic_operand" "s,s")] | |
722 | UNS_TPREL)))) | |
723 | (match_operand:SF 2 "mep_tprel_operand" "t,*r"))] | |
724 | "" | |
725 | "sw\\t%2, %%tpoff(%1)(%0)" | |
726 | [(set_attr "length" "2,4") | |
727 | (set_attr "stall" "store")]) | |
728 | ||
729 | (define_insn "*movsf_internal" | |
730 | [(set (match_operand:SF 0 "mep_movdest_operand" | |
731 | "=r,r,r,r,Z,m,r,c,r,y,r,er,ex,em,U") | |
732 | (match_operand:SF 1 "general_operand" | |
733 | " r,F,Z,m,r,r,c,r,y,r,er,r,ex,U,em"))] | |
734 | "mep_mov_ok (operands, SFmode)" | |
735 | "@ | |
736 | mov\\t%0, %1 | |
737 | # | |
738 | ldcb\\t%0, %1 | |
739 | lw\\t%0, %1 | |
740 | stcb\\t%1, %0 | |
741 | sw\\t%1, %0 | |
742 | ldc\\t%0, %1 | |
743 | stc\\t%1, %0 | |
744 | cmovc\\t%0, %1 | |
745 | cmovc\\t%0, %1 | |
746 | cmov\\t%0, %1 | |
747 | cmov\\t%0, %1 | |
748 | %<\\t%0, %M1 | |
749 | lwcp\\t%0, %1 | |
750 | swcp\\t%1, %0" | |
751 | [(set_attr "length" "2,*,2,*,2,*,2,2,*,*,4,4,*,*,*") | |
752 | (set_attr "intrinsic" "*,*,*,*,*,*,*,*,cmovc2,cmovc1,cmov2,cmov1,cmov,*,*") | |
753 | (set_attr "stall" "*,*,ldcb,load,stcb,store,ldc,stc,*,*,*,*,*,load,store") | |
754 | (set_attr "memop" "*,*,*,core1,*,core0,*,*,*,*,*,*,*,cop1,cop0")]) | |
755 | ||
756 | (define_split | |
757 | [(set (match_operand:SF 0 "register_operand" "") | |
758 | (match_operand:SF 1 "const_double_operand" ""))] | |
759 | "reload_completed" | |
760 | [(const_int 0)] | |
761 | " | |
762 | { | |
763 | REAL_VALUE_TYPE rv; | |
764 | HOST_WIDE_INT value; | |
765 | HOST_WIDE_INT lo, hi; | |
766 | rtx out; | |
767 | ||
768 | REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); | |
769 | REAL_VALUE_TO_TARGET_SINGLE (rv, value); | |
770 | ||
771 | lo = value & 0xffff; | |
772 | hi = trunc_int_for_mode (value & 0xffff0000, SImode); | |
773 | ||
774 | out = gen_rtx_REG (SImode, REGNO (operands[0])); | |
775 | emit_move_insn (out, GEN_INT (hi)); | |
776 | if (lo != 0) | |
777 | emit_insn (gen_iorsi3 (out, out, GEN_INT (lo))); | |
778 | DONE; | |
779 | }") | |
780 | ||
781 | (define_expand "movdf" | |
782 | [(set (match_operand:DF 0 "" "") | |
783 | (match_operand:DF 1 "" ""))] | |
784 | "" | |
785 | " | |
786 | { | |
787 | if (mep_expand_mov (operands, DFmode)) | |
788 | DONE; | |
789 | }") | |
790 | ||
791 | (define_insn "*movdf_internal_32" | |
792 | [(set (match_operand:DF 0 "mep_movdest_operand" "= r,m,r,c,r,er,ex,em,U") | |
793 | (match_operand:DF 1 "general_operand" "rFm,r,c,r,er,r,ex,U,em"))] | |
794 | "TARGET_32BIT_CR_REGS && mep_mov_ok (operands, DFmode)" | |
795 | "#" | |
796 | [(set_attr "slot" "multi")]) | |
797 | ||
798 | (define_insn "*movdf_internal_64" | |
799 | [(set (match_operand:DF 0 "mep_movdest_operand" "= r,m,r,c,r,er,ex,em,U") | |
800 | (match_operand:DF 1 "general_operand" "rFm,r,c,r,er,r,ex,U,em"))] | |
801 | "TARGET_64BIT_CR_REGS && mep_mov_ok (operands, DFmode)" | |
802 | "@ | |
803 | # | |
804 | # | |
805 | # | |
806 | # | |
807 | # | |
808 | # | |
809 | %<\\t%0, %M1 | |
810 | lmcp\\t%0, %1 | |
811 | smcp\\t%1, %0" | |
812 | [(set_attr "slot" "multi,multi,multi,multi,multi,multi,*,*,*") | |
813 | (set_attr "intrinsic" "*,*,*,*,*,*,cmov,*,*") | |
814 | (set_attr "memop" "*,*,*,*,*,*,*,cop1,cop0") | |
815 | (set_attr "stall" "*,*,*,*,*,*,*,load,store")]) | |
816 | ||
817 | (define_split | |
818 | [(set (match_operand:DF 0 "mep_movdest_operand" "") | |
819 | (match_operand:DF 1 "general_operand" ""))] | |
820 | "reload_completed && mep_multi_slot (insn)" | |
821 | [(set (match_dup 2) (match_dup 3)) | |
822 | (set (match_dup 4) (match_dup 5))] | |
823 | "mep_split_wide_move (operands, DFmode);") | |
824 | ||
825 | \f | |
826 | (define_insn "*lbcpa" | |
827 | [(set (match_operand:SI 0 "register_operand" "=em") | |
828 | (sign_extend:SI (mem:QI (match_operand:SI 2 "register_operand" "1")))) | |
829 | (set (match_operand:SI 1 "register_operand" "=r") | |
830 | (plus:SI (match_dup 2) | |
831 | (match_operand:SI 3 "cgen_h_sint_8a1_immediate" "")))] | |
832 | "TARGET_COP && reload_completed" | |
833 | "lbcpa\t%0, (%1+), %3" | |
834 | [(set_attr "length" "4") | |
835 | (set_attr "stall" "load")]) | |
836 | ||
837 | (define_insn "*sbcpa" | |
838 | [(set (mem:QI (match_operand:SI 1 "register_operand" "0")) | |
839 | (match_operand:QI 2 "register_operand" "em")) | |
840 | (set (match_operand:SI 0 "register_operand" "=r") | |
841 | (plus:SI (match_dup 1) | |
842 | (match_operand:SI 3 "cgen_h_sint_8a1_immediate" "")))] | |
843 | "TARGET_COP && reload_completed" | |
844 | "sbcpa\t%2, (%0+), %3" | |
845 | [(set_attr "length" "4") | |
846 | (set_attr "stall" "store")]) | |
847 | ||
848 | (define_insn "*lhcpa" | |
849 | [(set (match_operand:SI 0 "register_operand" "=em") | |
850 | (sign_extend:SI (mem:HI (match_operand:SI 2 "register_operand" "1")))) | |
851 | (set (match_operand:SI 1 "register_operand" "=r") | |
852 | (plus:SI (match_dup 2) | |
853 | (match_operand:SI 3 "cgen_h_sint_7a2_immediate" "")))] | |
854 | "TARGET_COP && reload_completed" | |
855 | "lhcpa\t%0, (%1+), %3" | |
856 | [(set_attr "length" "4") | |
857 | (set_attr "stall" "load")]) | |
858 | ||
859 | (define_insn "*shcpa" | |
860 | [(set (mem:HI (match_operand:SI 1 "register_operand" "0")) | |
861 | (match_operand:HI 2 "register_operand" "em")) | |
862 | (set (match_operand:SI 0 "register_operand" "=r") | |
863 | (plus:SI (match_dup 1) | |
864 | (match_operand:SI 3 "cgen_h_sint_7a2_immediate" "")))] | |
865 | "TARGET_COP && reload_completed" | |
866 | "shcpa\t%2, (%0+), %3" | |
867 | [(set_attr "length" "4") | |
868 | (set_attr "stall" "store")]) | |
869 | ||
870 | (define_insn "*lwcpi" | |
871 | [(set (match_operand:SI 0 "register_operand" "=em") | |
872 | (mem:SI (match_operand:SI 2 "register_operand" "1"))) | |
873 | (set (match_operand:SI 1 "register_operand" "=r") | |
874 | (plus:SI (match_dup 2) | |
875 | (const_int 4)))] | |
876 | "TARGET_COP && reload_completed" | |
877 | "lwcpi\t%0, (%1+)" | |
878 | [(set_attr "length" "2") | |
879 | (set_attr "stall" "load")]) | |
880 | ||
881 | (define_insn "*lwcpa" | |
882 | [(set (match_operand:SI 0 "register_operand" "=em") | |
883 | (mem:SI (match_operand:SI 2 "register_operand" "1"))) | |
884 | (set (match_operand:SI 1 "register_operand" "=r") | |
885 | (plus:SI (match_dup 2) | |
886 | (match_operand:SI 3 "cgen_h_sint_6a4_immediate" "")))] | |
887 | "TARGET_COP && reload_completed" | |
888 | "lwcpa\t%0, (%1+), %3" | |
889 | [(set_attr "length" "4") | |
890 | (set_attr "stall" "load")]) | |
891 | ||
892 | (define_insn "*swcpi" | |
893 | [(set (mem:SI (match_operand:SI 1 "register_operand" "0")) | |
894 | (match_operand:SI 2 "register_operand" "em")) | |
895 | (set (match_operand:SI 0 "register_operand" "=r") | |
896 | (plus:SI (match_dup 1) | |
897 | (const_int 4)))] | |
898 | "TARGET_COP && reload_completed" | |
899 | "swcpi\t%2, (%0+)" | |
900 | [(set_attr "length" "2") | |
901 | (set_attr "stall" "store")]) | |
902 | ||
903 | (define_insn "*swcpa" | |
904 | [(set (mem:SI (match_operand:SI 1 "register_operand" "0")) | |
905 | (match_operand:SI 2 "register_operand" "em")) | |
906 | (set (match_operand:SI 0 "register_operand" "=r") | |
907 | (plus:SI (match_dup 1) | |
908 | (match_operand:SI 3 "cgen_h_sint_6a4_immediate" "")))] | |
909 | "TARGET_COP && reload_completed" | |
910 | "swcpa\t%2, (%0+), %3" | |
911 | [(set_attr "length" "4") | |
912 | (set_attr "stall" "store")]) | |
913 | ||
914 | (define_peephole2 | |
915 | [(set (match_operand:SI 0 "register_operand" "") | |
916 | (plus:SI (match_dup 0) | |
917 | (match_operand:SI 1 "cgen_h_sint_8a1_immediate" "")))] | |
918 | "TARGET_COP && mep_use_post_modify_p (insn, operands[0], operands[1])" | |
919 | [(const_int 0)] | |
920 | { | |
921 | emit_note (NOTE_INSN_DELETED); | |
922 | DONE; | |
923 | }) | |
924 | \f | |
925 | ;; :::::::::::::::::::: | |
926 | ;; :: | |
927 | ;; :: Reloads | |
928 | ;; :: | |
929 | ;; :::::::::::::::::::: | |
930 | ||
931 | (define_expand "reload_insi" | |
932 | [(set (match_operand:SI 0 "mep_reload_operand" "") | |
933 | (match_operand:SI 1 "mep_reload_operand" "r")) | |
934 | (clobber (match_operand:SI 2 "register_operand" "=&r"))] | |
935 | "" | |
936 | " | |
937 | { | |
938 | mep_expand_reload (operands, SImode); | |
939 | DONE; | |
940 | }") | |
941 | ||
942 | (define_expand "reload_outsi" | |
943 | [(set (match_operand:SI 0 "mep_reload_operand" "=r") | |
944 | (match_operand:SI 1 "mep_reload_operand" "")) | |
945 | (clobber (match_operand:SI 2 "register_operand" "=&r"))] | |
946 | "" | |
947 | " | |
948 | { | |
949 | mep_expand_reload (operands, SImode); | |
950 | DONE; | |
951 | }") | |
952 | ||
953 | \f | |
954 | ;; :::::::::::::::::::: | |
955 | ;; :: | |
956 | ;; :: Conversions | |
957 | ;; :: | |
958 | ;; :::::::::::::::::::: | |
959 | ||
960 | (define_insn "extendqisi2" | |
961 | [(set (match_operand:SI 0 "register_operand" "=r,r,em") | |
962 | (sign_extend:SI | |
963 | (match_operand:QI 1 "nonimmediate_operand" "0,m,Y")))] | |
964 | "" | |
965 | "@ | |
966 | extb\\t%0 | |
967 | lb\\t%0, %1 | |
968 | lbcpa\\t%0, %P1" | |
969 | [(set_attr "length" "2,*,*") | |
970 | (set_attr "stall" "*,load,load") | |
971 | (set_attr "memop" "*,core1,cop1")]) | |
972 | ||
973 | (define_insn "extendhisi2" | |
974 | [(set (match_operand:SI 0 "register_operand" "=r,r,em") | |
975 | (sign_extend:SI | |
976 | (match_operand:HI 1 "nonimmediate_operand" "0,m,Y")))] | |
977 | "" | |
978 | "@ | |
979 | exth\\t%0 | |
980 | lh\\t%0, %1 | |
981 | lhcpa\\t%0, %P1" | |
982 | [(set_attr "length" "2,*,*") | |
983 | (set_attr "stall" "*,load,load") | |
984 | (set_attr "memop" "*,core1,cop1")]) | |
985 | ||
986 | (define_insn "zero_extendqisi2" | |
987 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
988 | (zero_extend:SI | |
989 | (match_operand:QI 1 "nonimmediate_operand" "0,r,m")))] | |
990 | "" | |
991 | "@ | |
992 | extub\\t%0 | |
993 | and3\\t%0, %1, 255 | |
994 | lbu\\t%0, %1" | |
995 | [(set_attr "length" "2,4,*") | |
996 | (set_attr "stall" "*,*,load") | |
997 | (set_attr "memop" "*,*,core1")]) | |
998 | ||
999 | (define_insn "zero_extendhisi2" | |
1000 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1001 | (zero_extend:SI | |
1002 | (match_operand:HI 1 "nonimmediate_operand" "0,r,m")))] | |
1003 | "" | |
1004 | "@ | |
1005 | extuh\\t%0 | |
1006 | and3\\t%0, %1, 65535 | |
1007 | lhu\\t%0, %1" | |
1008 | [(set_attr "length" "2,4,*") | |
1009 | (set_attr "stall" "*,*,load") | |
1010 | (set_attr "memop" "*,*,core1")]) | |
1011 | \f | |
1012 | ;; :::::::::::::::::::: | |
1013 | ;; :: | |
1014 | ;; :: 32 bit Integer arithmetic | |
1015 | ;; :: | |
1016 | ;; :::::::::::::::::::: | |
1017 | ||
1018 | (define_insn "addsi3" | |
1019 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1020 | (plus:SI (match_operand:SI 1 "register_operand" "%r,0,r") | |
1021 | (match_operand:SI 2 "mep_add_operand" "r,L,IT")))] | |
1022 | "" | |
1023 | "@ | |
1024 | add3\\t%0, %1, %2 | |
1025 | add\\t%0, %2 | |
1026 | add3\\t%0, %1, %I2" | |
1027 | [(set (attr "length") | |
1028 | (if_then_else (eq_attr "alternative" "2") | |
1029 | (if_then_else (and (match_operand:SI 1 "mep_sp_operand" "") | |
1030 | (match_operand:SI 2 "mep_imm7a4_operand" "")) | |
1031 | (const_int 2) | |
1032 | (const_int 4)) | |
1033 | (const_int 2)))]) | |
1034 | ||
1035 | ;; The intention here is to combine the 16-bit add with the 16-bit | |
1036 | ;; move to create a 32-bit add. It's the same size, but takes one | |
1037 | ;; less machine cycle. It will happen to match a 32-bit add with a | |
1038 | ;; 16-bit move also, but gcc shouldn't be doing that ;) | |
1039 | (define_peephole2 | |
1040 | [(set (match_operand:SI 0 "register_operand" "") | |
1041 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
1042 | (match_operand:SI 2 "immediate_operand" ""))) | |
1043 | (set (match_operand:SI 3 "register_operand" "") | |
1044 | (match_operand:SI 4 "register_operand" ""))] | |
1045 | "REGNO (operands[0]) == REGNO (operands[1]) | |
1046 | && REGNO (operands[0]) == REGNO (operands[4]) | |
1047 | && GR_REGNO_P (REGNO (operands[3])) | |
1048 | && dead_or_set_p (peep2_next_insn (1), operands[4])" | |
1049 | [(set (match_dup 3) | |
1050 | (plus:SI (match_dup 1) | |
1051 | (match_dup 2)))] | |
1052 | "") | |
1053 | ||
1054 | (define_insn "subsi3" | |
1055 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1056 | (minus:SI (match_operand:SI 1 "register_operand" "0") | |
1057 | (match_operand:SI 2 "register_operand" "r")))] | |
1058 | "" | |
1059 | "sub\\t%0, %2" | |
1060 | [(set_attr "length" "2")]) | |
1061 | ||
1062 | (define_expand "mulsi3" | |
1063 | [(set (match_operand:SI 0 "register_operand" "") | |
1064 | (mult:SI (match_operand:SI 1 "register_operand" "") | |
1065 | (match_operand:SI 2 "register_operand" "")))] | |
1066 | "TARGET_OPT_MULT || TARGET_COPRO_MULT" | |
1067 | { | |
1068 | emit_insn (gen_mulsi3_1 (operands[0], operands[1], operands[2])); | |
1069 | DONE; | |
1070 | }) | |
1071 | ||
1072 | ;; Generated by mep_reuse_lo_p when no GPR destination is needed. | |
1073 | (define_insn "mulsi3_lo" | |
1074 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1075 | (mult:SI (match_operand:SI 1 "register_operand" "r") | |
1076 | (match_operand:SI 2 "register_operand" "r"))) | |
1077 | (clobber (match_scratch:SI 3 "=h"))] | |
1078 | "TARGET_OPT_MULT && reload_completed" | |
1079 | "mul\\t%1, %2" | |
1080 | [(set_attr "length" "2") | |
1081 | (set_attr "stall" "mul")]) | |
1082 | ||
1083 | ;; Generated by mep_reuse_lo_p when both destinations of a mulr | |
1084 | ;; are needed. | |
1085 | (define_insn "mulsi3r" | |
1086 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1087 | (mult:SI (match_operand:SI 2 "register_operand" "1") | |
1088 | (match_operand:SI 3 "register_operand" "r"))) | |
1089 | (set (match_operand:SI 1 "register_operand" "=r") | |
1090 | (mult:SI (match_dup 2) | |
1091 | (match_dup 3))) | |
1092 | (clobber (match_scratch:SI 4 "=h"))] | |
1093 | "TARGET_OPT_MULT && reload_completed" | |
1094 | "mulr\\t%2, %3" | |
1095 | [(set_attr "length" "2") | |
1096 | (set_attr "stall" "mulr")]) | |
1097 | ||
1098 | (define_insn "mulsi3_1" | |
1099 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1100 | (mult:SI (match_operand:SI 1 "register_operand" "%0") | |
1101 | (match_operand:SI 2 "register_operand" "r"))) | |
1102 | (clobber (match_scratch:SI 3 "=l")) | |
1103 | (clobber (match_scratch:SI 4 "=h"))] | |
1104 | "TARGET_OPT_MULT" | |
1105 | "mulr\\t%1, %2" | |
1106 | [(set_attr "length" "2") | |
1107 | (set_attr "stall" "mulr")]) | |
1108 | ||
1109 | (define_expand "mulsidi3" | |
1110 | [(set (match_operand:DI 0 "register_operand" "") | |
1111 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) | |
1112 | (sign_extend:DI (match_operand:SI 2 "register_operand" ""))))] | |
1113 | "TARGET_OPT_MULT" | |
1114 | " | |
1115 | { | |
1116 | rtx hi = gen_reg_rtx (SImode); | |
1117 | rtx lo = gen_reg_rtx (SImode); | |
1118 | ||
1119 | emit_insn (gen_mulsidi3_i (hi, lo, operands[1], operands[2])); | |
1120 | emit_move_insn (gen_lowpart (SImode, operands[0]), lo); | |
1121 | emit_move_insn (gen_highpart (SImode, operands[0]), hi); | |
1122 | DONE; | |
1123 | }") | |
1124 | ||
1125 | (define_insn "mulsidi3_i" | |
1126 | [(set (match_operand:SI 0 "mep_hi_operand" "=h") | |
1127 | (truncate:SI | |
1128 | (lshiftrt:DI | |
1129 | (mult:DI (sign_extend:DI | |
1130 | (match_operand:SI 2 "register_operand" "r")) | |
1131 | (sign_extend:DI | |
1132 | (match_operand:SI 3 "register_operand" "r"))) | |
1133 | (const_int 32)))) | |
1134 | (set (match_operand:SI 1 "mep_lo_operand" "=l") | |
1135 | (mult:SI (match_dup 2) | |
1136 | (match_dup 3)))] | |
1137 | "TARGET_OPT_MULT" | |
1138 | "mul\\t%2, %3" | |
1139 | [(set_attr "length" "2") | |
1140 | (set_attr "stall" "mul")]) | |
1141 | ||
1142 | (define_insn "smulsi3_highpart" | |
1143 | [(set (match_operand:SI 0 "mep_hi_operand" "=h") | |
1144 | (truncate:SI | |
1145 | (lshiftrt:DI | |
1146 | (mult:DI (sign_extend:DI | |
1147 | (match_operand:SI 1 "register_operand" "r")) | |
1148 | (sign_extend:DI | |
1149 | (match_operand:SI 2 "register_operand" "r"))) | |
1150 | (const_int 32)))) | |
1151 | (clobber (reg:SI LO_REGNO))] | |
1152 | "TARGET_OPT_MULT" | |
1153 | "mul\\t%1, %2" | |
1154 | [(set_attr "length" "2") | |
1155 | (set_attr "stall" "mul")]) | |
1156 | ||
1157 | (define_expand "umulsidi3" | |
1158 | [(set (match_operand:DI 0 "mep_hi_operand" "") | |
1159 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) | |
1160 | (zero_extend:DI (match_operand:SI 2 "register_operand" ""))))] | |
1161 | "TARGET_OPT_MULT" | |
1162 | " | |
1163 | { | |
1164 | rtx hi = gen_reg_rtx (SImode); | |
1165 | rtx lo = gen_reg_rtx (SImode); | |
1166 | ||
1167 | emit_insn (gen_umulsidi3_i (hi, lo, operands[1], operands[2])); | |
1168 | emit_move_insn (gen_lowpart (SImode, operands[0]), lo); | |
1169 | emit_move_insn (gen_highpart (SImode, operands[0]), hi); | |
1170 | DONE; | |
1171 | }") | |
1172 | ||
1173 | (define_insn "umulsidi3_i" | |
1174 | [(set (match_operand:SI 0 "mep_hi_operand" "=h") | |
1175 | (truncate:SI | |
1176 | (lshiftrt:DI | |
1177 | (mult:DI (zero_extend:DI | |
1178 | (match_operand:SI 2 "register_operand" "r")) | |
1179 | (zero_extend:DI | |
1180 | (match_operand:SI 3 "register_operand" "r"))) | |
1181 | (const_int 32)))) | |
1182 | (set (match_operand:SI 1 "mep_lo_operand" "=l") | |
1183 | (mult:SI (match_dup 2) | |
1184 | (match_dup 3)))] | |
1185 | "TARGET_OPT_MULT" | |
1186 | "mulu\\t%2, %3" | |
1187 | [(set_attr "length" "2") | |
1188 | (set_attr "stall" "mul")]) | |
1189 | ||
1190 | (define_insn "umulsi3_highpart" | |
1191 | [(set (match_operand:SI 0 "mep_hi_operand" "=h") | |
1192 | (truncate:SI | |
1193 | (lshiftrt:DI | |
1194 | (mult:DI (zero_extend:DI | |
1195 | (match_operand:SI 1 "register_operand" "r")) | |
1196 | (zero_extend:DI | |
1197 | (match_operand:SI 2 "register_operand" "r"))) | |
1198 | (const_int 32)))) | |
1199 | (clobber (reg:SI LO_REGNO))] | |
1200 | "TARGET_OPT_MULT" | |
1201 | "mulu %1, %2" | |
1202 | [(set_attr "length" "2") | |
1203 | (set_attr "stall" "mul")]) | |
1204 | ||
1205 | ;; These two don't currently match because we don't have an adddi3 pattern. | |
1206 | (define_insn "*smultdi_and_add" | |
1207 | [(set (match_operand:DI 0 "mep_hi_operand" "=d") | |
1208 | (plus:DI (mult:DI (zero_extend:DI | |
1209 | (match_operand:SI 1 "register_operand" "r")) | |
1210 | (zero_extend:DI | |
1211 | (match_operand:SI 2 "register_operand" "r"))) | |
1212 | (match_operand:DI 3 "mep_hi_operand" "0")))] | |
1213 | "TARGET_OPT_MULT && TARGET_BIG_ENDIAN" | |
1214 | "maddu\\t%1, %2" | |
1215 | [(set_attr "length" "4") | |
1216 | (set_attr "stall" "mul")]) | |
1217 | ||
1218 | (define_insn "*umultdi_and_add" | |
1219 | [(set (match_operand:DI 0 "mep_hi_operand" "=d") | |
1220 | (plus:DI (mult:DI (sign_extend:DI | |
1221 | (match_operand:SI 1 "register_operand" "r")) | |
1222 | (sign_extend:DI | |
1223 | (match_operand:SI 2 "register_operand" "r"))) | |
1224 | (match_operand:DI 3 "mep_hi_operand" "0")))] | |
1225 | "TARGET_OPT_MULT && TARGET_BIG_ENDIAN" | |
1226 | "madd\\t%1, %2" | |
1227 | [(set_attr "length" "4") | |
1228 | (set_attr "stall" "mul")]) | |
1229 | ||
1230 | ;; A pattern for 'r1 = r2 * r3 + r4'. There are three possible | |
1231 | ;; implementations: | |
1232 | ;; | |
1233 | ;; (1) 'mulr;add3'. This is usually the best choice if the instruction | |
1234 | ;; is not part of a natural multiply-accumulate chain. It has the | |
1235 | ;; same latency as 'stc;maddr' but doesn't tie up $lo for as long. | |
1236 | ;; | |
1237 | ;; (2) 'madd'. This is the best choice if the instruction is in the | |
1238 | ;; middle of a natural multiply-accumulate chain. r4 will already | |
1239 | ;; be in $lo and r1 will also be needed in $lo. | |
1240 | ;; | |
1241 | ;; (3) 'maddr'. This is the best choice if the instruction is at the | |
1242 | ;; end of a natural multiply-accumulate chain. r4 will be in $lo | |
1243 | ;; but r1 will be needed in a GPR. | |
1244 | ;; | |
1245 | ;; In theory, we could put all the alternatives into a single pattern and | |
1246 | ;; leave the register allocator to choose between them. However, this can | |
1247 | ;; sometimes produce poor results in practice. | |
1248 | ;; | |
1249 | ;; This pattern therefore describes a general GPR-to-GPR operation that | |
1250 | ;; has a slight preference for cases in which operands 0 and 1 are tied. | |
1251 | ;; After reload, we try to rewrite the patterns using peephole2s (if | |
1252 | ;; enabled), falling back on define_splits if that fails. See also | |
1253 | ;; mep_reuse_lo_p. | |
1254 | (define_insn "maddsi3" | |
1255 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1256 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%0,r") | |
1257 | (match_operand:SI 2 "register_operand" "r,r")) | |
1258 | (match_operand:SI 3 "register_operand" "r,r"))) | |
1259 | (clobber (match_scratch:SI 4 "=l,l")) | |
1260 | (clobber (match_scratch:SI 5 "=h,h"))] | |
1261 | "TARGET_OPT_MULT" | |
1262 | "#" | |
1263 | [(set_attr "length" "8") | |
1264 | (set_attr "stall" "mulr")]) | |
1265 | ||
1266 | ;; Implement maddsi3s using maddr if operand 3 is already available in $lo. | |
1267 | (define_peephole2 | |
1268 | [(parallel | |
1269 | [(set (match_operand:SI 0 "register_operand" "") | |
1270 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") | |
1271 | (match_operand:SI 2 "register_operand" "")) | |
1272 | (match_operand:SI 3 "register_operand" ""))) | |
1273 | (clobber (match_scratch:SI 4 "")) | |
1274 | (clobber (match_scratch:SI 5 ""))])] | |
1275 | "TARGET_OPT_MULT | |
1276 | && reload_completed | |
1277 | && mep_reuse_lo_p (operands[4], operands[3], insn, | |
1278 | !rtx_equal_p (operands[1], operands[3]) | |
1279 | && !rtx_equal_p (operands[2], operands[3]) | |
1280 | && (rtx_equal_p (operands[0], operands[3]) | |
1281 | || peep2_reg_dead_p (1, operands[3])))" | |
1282 | [(parallel | |
1283 | [(set (match_dup 4) | |
1284 | (plus:SI (mult:SI (match_dup 0) | |
1285 | (match_dup 2)) | |
1286 | (match_dup 4))) | |
1287 | (set (match_dup 0) | |
1288 | (plus:SI (mult:SI (match_dup 0) | |
1289 | (match_dup 2)) | |
1290 | (match_dup 4))) | |
1291 | (clobber (match_dup 5))])] | |
1292 | "operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]);") | |
1293 | ||
1294 | ;; This splitter implements maddsi3 as "mulr;add3". It only works if | |
1295 | ;; operands 0 and 3 are distinct, since operand 0 is clobbered before | |
1296 | ;; operand 3 is used. | |
1297 | (define_split | |
1298 | [(set (match_operand:SI 0 "register_operand" "") | |
1299 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") | |
1300 | (match_operand:SI 2 "register_operand" "")) | |
1301 | (match_operand:SI 3 "register_operand" ""))) | |
1302 | (clobber (match_scratch:SI 4 "")) | |
1303 | (clobber (match_scratch:SI 5 ""))] | |
1304 | "TARGET_OPT_MULT | |
1305 | && reload_completed | |
1306 | && !rtx_equal_p (operands[0], operands[3])" | |
1307 | [(parallel [(set (match_dup 0) | |
1308 | (mult:SI (match_dup 0) | |
1309 | (match_dup 2))) | |
1310 | (clobber (match_dup 4)) | |
1311 | (clobber (match_dup 5))]) | |
1312 | (set (match_dup 0) | |
1313 | (plus:SI (match_dup 0) | |
1314 | (match_dup 3)))] | |
1315 | "operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]);") | |
1316 | ||
1317 | ;; This is the fallback splitter for maddsi3. It moves operand 3 into | |
1318 | ;; $lo and then uses maddr. | |
1319 | (define_split | |
1320 | [(set (match_operand:SI 0 "register_operand" "") | |
1321 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") | |
1322 | (match_operand:SI 2 "register_operand" "")) | |
1323 | (match_operand:SI 3 "register_operand" ""))) | |
1324 | (clobber (match_scratch:SI 4 "")) | |
1325 | (clobber (match_scratch:SI 5 ""))] | |
1326 | "TARGET_OPT_MULT | |
1327 | && reload_completed" | |
1328 | [(parallel [(set (match_dup 4) | |
1329 | (plus:SI (mult:SI (match_dup 0) | |
1330 | (match_dup 2)) | |
1331 | (match_dup 4))) | |
1332 | (set (match_dup 0) | |
1333 | (plus:SI (mult:SI (match_dup 0) | |
1334 | (match_dup 2)) | |
1335 | (match_dup 4))) | |
1336 | (clobber (match_dup 5))])] | |
1337 | { | |
1338 | emit_move_insn (operands[4], operands[3]); | |
1339 | operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]); | |
1340 | }) | |
1341 | ||
1342 | ;; Remove unnecessary stcs to $lo. This cleans up the moves generated | |
1343 | ;; by earlier calls to mep_reuse_lo_p. | |
1344 | (define_peephole2 | |
1345 | [(set (match_operand:SI 0 "mep_lo_operand" "") | |
1346 | (match_operand:SI 1 "register_operand" ""))] | |
1347 | "TARGET_OPT_MULT | |
1348 | && mep_reuse_lo_p (operands[0], operands[1], insn, | |
1349 | peep2_reg_dead_p (1, operands[1]))" | |
1350 | [(const_int 0)] | |
1351 | { | |
1352 | emit_note (NOTE_INSN_DELETED); | |
1353 | DONE; | |
1354 | }) | |
1355 | ||
1356 | (define_insn "maddsi3_lo" | |
1357 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1358 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") | |
1359 | (match_operand:SI 2 "register_operand" "r")) | |
1360 | (match_operand:SI 3 "mep_lo_operand" "0"))) | |
1361 | (clobber (match_scratch:SI 4 "=h"))] | |
1362 | "TARGET_OPT_MULT && reload_completed" | |
1363 | "madd\\t%1, %2" | |
1364 | [(set_attr "length" "4") | |
1365 | (set_attr "stall" "mul")]) | |
1366 | ||
1367 | (define_insn "maddsi3r" | |
1368 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1369 | (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "1") | |
1370 | (match_operand:SI 3 "register_operand" "r")) | |
1371 | (match_operand:SI 4 "register_operand" "0"))) | |
1372 | (set (match_operand:SI 1 "register_operand" "=r") | |
1373 | (plus:SI (mult:SI (match_dup 2) | |
1374 | (match_dup 3)) | |
1375 | (match_dup 4))) | |
1376 | (clobber (match_scratch:SI 5 "=h"))] | |
1377 | "TARGET_OPT_MULT && reload_completed" | |
1378 | "maddr\\t%2, %3" | |
1379 | [(set_attr "length" "4") | |
1380 | (set_attr "stall" "mulr")]) | |
1381 | ||
1382 | (define_insn "*shift_1_or_2_and_add" | |
1383 | [(set (match_operand:SI 0 "mep_r0_operand" "=z") | |
1384 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") | |
1385 | (match_operand:SI 2 "mep_slad_operand" "n")) | |
1386 | (match_operand:SI 3 "register_operand" "r")))] | |
1387 | "" | |
1388 | "sl%b2ad3\\t%0, %1, %3" | |
1389 | [(set_attr "length" "2") | |
1390 | (set_attr "stall" "int2")]) | |
1391 | ||
1392 | (define_insn "divmodsi4" | |
1393 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1394 | (div:SI (match_operand:SI 1 "register_operand" "r") | |
1395 | (match_operand:SI 2 "register_operand" "r"))) | |
1396 | (set (match_operand:SI 3 "mep_hi_operand" "=h") | |
1397 | (mod:SI (match_dup 1) | |
1398 | (match_dup 2)))] | |
1399 | "TARGET_OPT_DIV" | |
1400 | "div\\t%1, %2" | |
1401 | [(set_attr "length" "2") | |
1402 | (set_attr "stall" "div") | |
1403 | (set_attr "may_trap" "yes")]) | |
1404 | ||
1405 | (define_insn "udivmodsi4" | |
1406 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1407 | (udiv:SI (match_operand:SI 1 "register_operand" "r") | |
1408 | (match_operand:SI 2 "register_operand" "r"))) | |
1409 | (set (match_operand:SI 3 "mep_hi_operand" "=h") | |
1410 | (umod:SI (match_dup 1) | |
1411 | (match_dup 2)))] | |
1412 | "TARGET_OPT_DIV" | |
1413 | "divu\\t%1, %2" | |
1414 | [(set_attr "length" "2") | |
1415 | (set_attr "stall" "div") | |
1416 | (set_attr "may_trap" "yes")]) | |
1417 | ||
1418 | (define_insn "negsi2" | |
1419 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1420 | (neg:SI (match_operand:SI 1 "register_operand" "r")))] | |
1421 | "" | |
1422 | "neg\\t%0, %1" | |
1423 | [(set_attr "length" "2")]) | |
1424 | ||
1425 | ;; We have "absolute difference between two regs" which isn't quite | |
1426 | ;; what gcc is expecting. | |
1427 | (define_expand "abssi2" | |
1428 | [(set (match_dup 2) (const_int 0)) | |
1429 | (set (match_operand:SI 0 "register_operand" "") | |
1430 | (abs:SI (minus:SI (match_operand:SI 1 "register_operand" "") | |
1431 | (match_dup 2)) | |
1432 | ))] | |
1433 | "TARGET_OPT_ABSDIFF" | |
1434 | "operands[2] = gen_reg_rtx (SImode);") | |
1435 | ||
1436 | (define_insn "*absdiff" | |
1437 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1438 | (abs:SI (minus:SI (match_operand:SI 1 "register_operand" "0") | |
1439 | (match_operand:SI 2 "register_operand" "r"))))] | |
1440 | "TARGET_OPT_ABSDIFF" | |
1441 | "abs\\t%0, %2" | |
1442 | [(set_attr "length" "4")]) | |
1443 | ||
1444 | (define_split | |
1445 | [(set (match_operand:SI 0 "register_operand" "") | |
1446 | (abs:SI (plus:SI (match_operand:SI 1 "register_operand" "") | |
1447 | (match_operand:SI 2 "immediate_operand" "")))) | |
1448 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
1449 | "!reload_completed" | |
1450 | [(set (match_dup 3) | |
1451 | (match_dup 4)) | |
1452 | (set (match_operand:SI 0 "register_operand" "") | |
1453 | (abs:SI (minus:SI (match_operand:SI 1 "register_operand" "") | |
1454 | (match_dup 3))))] | |
1455 | "operands[4] = GEN_INT (-INTVAL (operands[2]));") | |
1456 | ||
1457 | (define_insn "sminsi3" | |
1458 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1459 | (smin:SI (match_operand:SI 1 "register_operand" "0") | |
1460 | (match_operand:SI 2 "nonmemory_operand" "r")))] | |
1461 | "TARGET_OPT_MINMAX" | |
1462 | "min\\t%0, %2" | |
1463 | [(set_attr "length" "4")]) | |
1464 | ||
1465 | (define_insn "smaxsi3" | |
1466 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1467 | (smax:SI (match_operand:SI 1 "register_operand" "0") | |
1468 | (match_operand:SI 2 "nonmemory_operand" "r")))] | |
1469 | "TARGET_OPT_MINMAX" | |
1470 | "max\\t%0, %2" | |
1471 | [(set_attr "length" "4")]) | |
1472 | ||
1473 | (define_insn "uminsi3" | |
1474 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1475 | (umin:SI (match_operand:SI 1 "register_operand" "0") | |
1476 | (match_operand:SI 2 "nonmemory_operand" "r")))] | |
1477 | "TARGET_OPT_MINMAX" | |
1478 | "minu\\t%0, %2" | |
1479 | [(set_attr "length" "4")]) | |
1480 | ||
1481 | (define_insn "umaxsi3" | |
1482 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1483 | (umax:SI (match_operand:SI 1 "register_operand" "0") | |
1484 | (match_operand:SI 2 "nonmemory_operand" "r")))] | |
1485 | "TARGET_OPT_MINMAX" | |
1486 | "maxu\\t%0, %2" | |
1487 | [(set_attr "length" "4")]) | |
1488 | ||
1489 | ;; Average: a = (b+c+1)>>1 | |
1490 | (define_insn "*averagesi3" | |
1491 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1492 | (ashiftrt:SI (plus:SI (plus:SI | |
1493 | (match_operand:SI 1 "register_operand" "0") | |
1494 | (match_operand:SI 2 "register_operand" "r")) | |
1495 | (const_int 1)) | |
1496 | (const_int 1)))] | |
1497 | "TARGET_OPT_AVERAGE" | |
1498 | "ave\\t%0, %2" | |
1499 | [(set_attr "length" "4")]) | |
1500 | ||
1501 | ;; clip support | |
1502 | ||
1503 | (define_insn "clip_maxmin" | |
1504 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1505 | (smax:SI (smin:SI (match_operand:SI 1 "register_operand" "0") | |
1506 | (match_operand:SI 2 "immediate_operand" "n")) | |
1507 | (match_operand:SI 3 "immediate_operand" "n")))] | |
1508 | "mep_allow_clip (operands[2], operands[3], 1)" | |
1509 | "clip\\t%0, %B2" | |
1510 | [(set_attr "length" "4")]) | |
1511 | ||
1512 | (define_insn "clip_minmax" | |
1513 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1514 | (smin:SI (smax:SI (match_operand:SI 1 "register_operand" "0") | |
1515 | (match_operand:SI 2 "immediate_operand" "n")) | |
1516 | (match_operand:SI 3 "immediate_operand" "n")))] | |
1517 | "mep_allow_clip (operands[3], operands[2], 1)" | |
1518 | "clip\\t%0, %B3" | |
1519 | [(set_attr "length" "4")]) | |
1520 | ||
1521 | (define_insn "clipu_maxmin" | |
1522 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1523 | (smax:SI (smin:SI (match_operand:SI 1 "register_operand" "0") | |
1524 | (match_operand:SI 2 "immediate_operand" "n")) | |
1525 | (match_operand:SI 3 "immediate_operand" "n")))] | |
1526 | "mep_allow_clip (operands[2], operands[3], 0)" | |
1527 | "clipu\\t%0, %U2" | |
1528 | [(set_attr "length" "4")]) | |
1529 | ||
1530 | (define_insn "clipu_minmax" | |
1531 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1532 | (smin:SI (smax:SI (match_operand:SI 1 "register_operand" "0") | |
1533 | (match_operand:SI 2 "immediate_operand" "n")) | |
1534 | (match_operand:SI 3 "immediate_operand" "n")))] | |
1535 | "mep_allow_clip (operands[3], operands[2], 0)" | |
1536 | "clipu\\t%0, %U3" | |
1537 | [(set_attr "length" "4")]) | |
1538 | \f | |
1539 | ;; :::::::::::::::::::: | |
1540 | ;; :: | |
1541 | ;; :: 32 bit Integer Shifts and Rotates | |
1542 | ;; :: | |
1543 | ;; :::::::::::::::::::: | |
1544 | ||
1545 | (define_insn "ashlsi3" | |
1546 | [(set (match_operand:SI 0 "register_operand" "=r,z") | |
1547 | (ashift:SI (match_operand:SI 1 "register_operand" "0,r") | |
1548 | (match_operand:SI 2 "nonmemory_operand" "rM,M")))] | |
1549 | "" | |
1550 | "@ | |
1551 | sll\\t%0, %2 | |
1552 | sll3\\t%0, %1, %2" | |
1553 | [(set_attr "length" "2,2") | |
1554 | (set_attr "shiftop" "operand2")]) | |
1555 | ||
1556 | (define_insn "ashrsi3" | |
1557 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1558 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") | |
1559 | (match_operand:SI 2 "nonmemory_operand" "rM")))] | |
1560 | "" | |
1561 | "sra\\t%0, %2" | |
1562 | [(set_attr "length" "2") | |
1563 | (set_attr "shiftop" "operand2")]) | |
1564 | ||
1565 | (define_insn "lshrsi3" | |
1566 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1567 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") | |
1568 | (match_operand:SI 2 "nonmemory_operand" "rM")))] | |
1569 | "" | |
1570 | "srl\\t%0, %2" | |
1571 | [(set_attr "length" "2") | |
1572 | (set_attr "shiftop" "operand2")]) | |
1573 | \f | |
1574 | ;; :::::::::::::::::::: | |
1575 | ;; :: | |
1576 | ;; :: 32 Bit Integer Logical operations | |
1577 | ;; :: | |
1578 | ;; :::::::::::::::::::: | |
1579 | ||
1580 | (define_insn "andsi3" | |
1581 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1582 | (and:SI (match_operand:SI 1 "register_operand" "%0,r") | |
1583 | (match_operand:SI 2 "nonmemory_operand" "r,J")))] | |
1584 | "" | |
1585 | "@ | |
1586 | and\\t%0, %2 | |
1587 | and3\\t%0, %1, %J2" | |
1588 | [(set_attr "length" "2,4")]) | |
1589 | ||
1590 | (define_insn "iorsi3" | |
1591 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1592 | (ior:SI (match_operand:SI 1 "register_operand" "%0,r") | |
1593 | (match_operand:SI 2 "nonmemory_operand" "r,J")))] | |
1594 | "" | |
1595 | "@ | |
1596 | or\\t%0, %2 | |
1597 | or3\\t%0, %1, %J2" | |
1598 | [(set_attr "length" "2,4")]) | |
1599 | ||
1600 | (define_insn "xorsi3" | |
1601 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1602 | (xor:SI (match_operand:SI 1 "register_operand" "%0,r") | |
1603 | (match_operand:SI 2 "nonmemory_operand" "r,J")))] | |
1604 | "" | |
1605 | "@ | |
1606 | xor\\t%0, %2 | |
1607 | xor3\\t%0, %1, %J2" | |
1608 | [(set_attr "length" "2,4")]) | |
1609 | ||
1610 | (define_expand "one_cmplsi2" | |
1611 | [(set (match_operand:SI 0 "register_operand" "") | |
1612 | (not:SI (match_operand:SI 1 "register_operand" "")))] | |
1613 | "" | |
1614 | "operands[2] = operands[1]; | |
1615 | ") | |
1616 | ||
1617 | ;; No separate insn for this; use NOR | |
1618 | (define_insn "*one_cmplsi3_internal" | |
1619 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1620 | (not:SI (match_operand:SI 1 "register_operand" "0")))] | |
1621 | "" | |
1622 | "nor\\t%0, %0" | |
1623 | [(set_attr "length" "2")]) | |
1624 | \f | |
1625 | ;; :::::::::::::::::::: | |
1626 | ;; :: | |
1627 | ;; :: Bit Manipulation | |
1628 | ;; :: | |
1629 | ;; :::::::::::::::::::: | |
1630 | ||
1631 | (define_insn "*bitop_be" | |
1632 | [(set (match_operand:QI 0 "mep_Y_operand" "=Y") | |
1633 | (subreg:QI (match_operator:SI 3 "mep_bit_operator" | |
1634 | [(subreg:SI (match_operand:QI 1 "mep_Y_operand" "0") 0) | |
1635 | (match_operand 2 "immediate_operand" "n")]) | |
1636 | 3) | |
1637 | )] | |
1638 | "TARGET_BIG_ENDIAN && TARGET_OPT_BITOPS | |
1639 | && rtx_equal_p (operands[0], operands[1])" | |
1640 | "b%L3m\\t%0, %b2" | |
1641 | [(set_attr "length" "2")]) | |
1642 | ||
1643 | (define_insn "*bitop_le" | |
1644 | [(set (match_operand:QI 0 "mep_Y_operand" "=Y") | |
1645 | (subreg:QI (match_operator:SI 3 "mep_bit_operator" | |
1646 | [(subreg:SI (match_operand:QI 1 "mep_Y_operand" "0") 0) | |
1647 | (match_operand 2 "immediate_operand" "n")]) | |
1648 | 0) | |
1649 | )] | |
1650 | "!TARGET_BIG_ENDIAN && TARGET_OPT_BITOPS | |
1651 | && rtx_equal_p (operands[0], operands[1])" | |
1652 | "b%L3m\\t%0, %b2" | |
1653 | [(set_attr "length" "2")]) | |
1654 | ||
1655 | (define_insn "btstm" | |
1656 | [(set (match_operand:SI 0 "mep_r0_operand" "=z") | |
1657 | (and:SI (subreg:SI (match_operand:QI 1 "mep_Y_operand" "Y") 0) | |
1658 | (match_operand 2 "immediate_operand" "n")) | |
1659 | )] | |
1660 | "TARGET_OPT_BITOPS && mep_bit_position_p (operands[2], 1)" | |
1661 | "btstm\\t%0, %1, %b2" | |
1662 | [(set_attr "length" "2")]) | |
1663 | ||
1664 | (define_insn "tas" | |
1665 | [(parallel [(set (match_operand:SI 0 "mep_r0_operand" "=z") | |
1666 | (zero_extend:SI (match_operand:QI 1 "mep_Y_operand" "+Y"))) | |
1667 | (set (match_dup 1) | |
1668 | (const_int 1)) | |
1669 | ] | |
1670 | )] | |
1671 | "TARGET_OPT_BITOPS" | |
1672 | "tas\\t%0, %1" | |
1673 | [(set_attr "length" "2")]) | |
1674 | ||
1675 | (define_peephole2 | |
1676 | [(set (match_operand:SI 0 "mep_r0_operand" "") | |
1677 | (zero_extend:SI (match_operand:QI 1 "mep_Y_operand" ""))) | |
1678 | (set (match_operand:QI 2 "register_operand" "") | |
1679 | (const_int 1)) | |
1680 | (set (match_dup 1) | |
1681 | (match_dup 2)) | |
1682 | ] | |
1683 | "TARGET_OPT_BITOPS" | |
1684 | [(parallel [(set (match_dup 0) | |
1685 | (zero_extend:SI (match_dup 1))) | |
1686 | (set (match_dup 1) | |
1687 | (const_int 1)) | |
1688 | ])] | |
1689 | "") | |
1690 | ||
1691 | (define_peephole2 | |
1692 | [(set (match_operand:SI 0 "mep_r0_operand" "") | |
1693 | (sign_extend:SI (match_operand:QI 1 "mep_Y_operand" ""))) | |
1694 | (set (match_operand:QI 2 "register_operand" "") | |
1695 | (const_int 1)) | |
1696 | (set (match_dup 1) | |
1697 | (match_dup 2)) | |
1698 | ] | |
1699 | "TARGET_OPT_BITOPS" | |
1700 | [(parallel [(set (match_dup 0) | |
1701 | (zero_extend:SI (match_dup 1))) | |
1702 | (set (match_dup 1) | |
1703 | (const_int 1)) | |
1704 | ]) | |
1705 | (set (match_dup 0) | |
1706 | (sign_extend:SI (match_dup 3)))] | |
1707 | "operands[3] = gen_lowpart (QImode, operands[0]);") | |
1708 | ||
1709 | \f | |
1710 | ;; :::::::::::::::::::: | |
1711 | ;; :: | |
1712 | ;; :: Conditional branches and stores | |
1713 | ;; :: | |
1714 | ;; :::::::::::::::::::: | |
1715 | ||
1716 | (define_expand "cbranchsi4" | |
1717 | [(set (pc) | |
1718 | (if_then_else (match_operator 0 "ordered_comparison_operator" | |
1719 | [(match_operand:SI 1 "register_operand" "") | |
1720 | (match_operand:SI 2 "nonmemory_operand" "")]) | |
1721 | (label_ref (match_operand 3 "" "")) | |
1722 | (pc)))] | |
1723 | "" | |
1724 | "emit_jump_insn (gen_branch_true (operands[3], | |
1725 | mep_expand_cbranch (operands))); | |
1726 | DONE;") | |
1727 | ||
1728 | (define_expand "branch_true" | |
1729 | [(set (pc) | |
1730 | (if_then_else (match_operand 1 "" "") | |
1731 | (label_ref (match_operand 0 "" "")) | |
1732 | (pc)))] | |
1733 | "" | |
1734 | "") | |
1735 | ||
1736 | (define_expand "cstoresi4" | |
1737 | [(set (match_operand:SI 0 "register_operand" "") | |
1738 | (match_operator:SI 1 "ordered_comparison_operator" | |
1739 | [(match_operand:SI 2 "register_operand" "") | |
1740 | (match_operand:SI 3 "nonmemory_operand" "")]))] | |
1741 | "" | |
1742 | "if (mep_expand_setcc (operands)) DONE; else FAIL;") | |
1743 | ||
1744 | ;; ------------------------------------------------------------ | |
1745 | ||
1746 | (define_insn "*slt" | |
1747 | [(set (match_operand:SI 0 "register_operand" "=z,z,r") | |
1748 | (lt:SI (match_operand:SI 1 "register_operand" "r,r,r") | |
1749 | (match_operand:SI 2 "nonmemory_operand" "r,M,I")))] | |
1750 | "" | |
1751 | "slt3\\t%0, %1, %2" | |
1752 | [(set_attr "length" "2,2,4")]) | |
1753 | ||
1754 | (define_insn "*sltu" | |
1755 | [(set (match_operand:SI 0 "register_operand" "=z,z,r") | |
1756 | (ltu:SI (match_operand:SI 1 "register_operand" "r,r,r") | |
1757 | (match_operand:SI 2 "nonmemory_operand" "r,M,J")))] | |
1758 | "" | |
1759 | "sltu3\\t%0, %1, %2" | |
1760 | [(set_attr "length" "2,2,4")]) | |
1761 | ||
1762 | (define_insn "*bcpeq_true" | |
1763 | [(set (pc) | |
1764 | (if_then_else (eq:SI (reg:SI CBCR_REGNO) | |
1765 | (const_int 0)) | |
1766 | (label_ref (match_operand 0 "" "")) | |
1767 | (pc)))] | |
1768 | "" | |
1769 | "bcpeq\t0, %l0" | |
1770 | [(set_attr "length" "4")]) | |
1771 | ||
1772 | (define_insn "*bcpeq_false" | |
1773 | [(set (pc) | |
1774 | (if_then_else (eq:SI (reg:SI CBCR_REGNO) | |
1775 | (const_int 0)) | |
1776 | (pc) | |
1777 | (label_ref (match_operand 0 "" ""))))] | |
1778 | "" | |
1779 | "bcpne\t0, %l0" | |
1780 | [(set_attr "length" "4")]) | |
1781 | ||
1782 | (define_insn "*bcpne_true" | |
1783 | [(set (pc) | |
1784 | (if_then_else (ne:SI (reg:SI CBCR_REGNO) | |
1785 | (const_int 0)) | |
1786 | (label_ref (match_operand 0 "" "")) | |
1787 | (pc)))] | |
1788 | "" | |
1789 | "bcpne\t0, %l0" | |
1790 | [(set_attr "length" "4")]) | |
1791 | ||
1792 | (define_insn "*bcpne_false" | |
1793 | [(set (pc) | |
1794 | (if_then_else (ne:SI (reg:SI CBCR_REGNO) | |
1795 | (const_int 0)) | |
1796 | (pc) | |
1797 | (label_ref (match_operand 0 "" ""))))] | |
1798 | "" | |
1799 | "bcpeq\t0, %l0" | |
1800 | [(set_attr "length" "4")]) | |
1801 | ||
1802 | ;; ??? The lengths here aren't correct, since no attempt it made to | |
1803 | ;; find "beqz" in the 256-byte range. However, this should not affect | |
1804 | ;; bundling, since we never run core branches in parallel. | |
1805 | ||
1806 | (define_insn "mep_beq_true" | |
1807 | [(set (pc) | |
1808 | (if_then_else (eq (match_operand:SI 0 "register_operand" "r") | |
1809 | (match_operand:SI 1 "mep_reg_or_imm4_operand" "rN")) | |
1810 | (label_ref (match_operand 2 "" "")) | |
1811 | (pc)))] | |
1812 | "" | |
1813 | "* return mep_emit_cbranch (operands, 0);" | |
1814 | [(set_attr "length" "4")] ) | |
1815 | ||
1816 | (define_insn "*beq_false" | |
1817 | [(set (pc) | |
1818 | (if_then_else (eq (match_operand:SI 0 "register_operand" "r") | |
1819 | (match_operand:SI 1 "mep_reg_or_imm4_operand" "rN")) | |
1820 | (pc) | |
1821 | (label_ref (match_operand 2 "" ""))))] | |
1822 | "" | |
1823 | "* return mep_emit_cbranch (operands, 1);" | |
1824 | [(set_attr "length" "4")]) | |
1825 | ||
1826 | (define_insn "mep_bne_true" | |
1827 | [(set (pc) | |
1828 | (if_then_else (ne (match_operand:SI 0 "register_operand" "r") | |
1829 | (match_operand:SI 1 "mep_reg_or_imm4_operand" "rN")) | |
1830 | (label_ref (match_operand 2 "" "")) | |
1831 | (pc)))] | |
1832 | "" | |
1833 | "* return mep_emit_cbranch (operands, 1); " | |
1834 | [(set_attr "length" "4")]) | |
1835 | ||
1836 | (define_insn "*bne_false" | |
1837 | [(set (pc) | |
1838 | (if_then_else (ne (match_operand:SI 0 "register_operand" "r") | |
1839 | (match_operand:SI 1 "mep_reg_or_imm4_operand" "rN")) | |
1840 | (pc) | |
1841 | (label_ref (match_operand 2 "" ""))))] | |
1842 | "" | |
1843 | "* return mep_emit_cbranch (operands, 0); " | |
1844 | [(set_attr "length" "4")]) | |
1845 | ||
1846 | (define_insn "mep_blti" | |
1847 | [(set (pc) | |
1848 | (if_then_else (lt (match_operand:SI 0 "register_operand" "r") | |
1849 | (match_operand:SI 1 "mep_imm4_operand" "N")) | |
1850 | (label_ref (match_operand 2 "" "")) | |
1851 | (pc)))] | |
1852 | "" | |
1853 | "blti\\t%0, %1, %l2" | |
1854 | [(set_attr "length" "4")]) | |
1855 | ||
1856 | (define_insn "*bgei" | |
1857 | [(set (pc) | |
1858 | (if_then_else (ge (match_operand:SI 0 "register_operand" "r") | |
1859 | (match_operand:SI 1 "mep_imm4_operand" "N")) | |
1860 | (label_ref (match_operand 2 "" "")) | |
1861 | (pc)))] | |
1862 | "" | |
1863 | "bgei\\t%0, %1, %l2" | |
1864 | [(set_attr "length" "4")]) | |
1865 | \f | |
1866 | ;; :::::::::::::::::::: | |
1867 | ;; :: | |
1868 | ;; :: Call and branch instructions | |
1869 | ;; :: | |
1870 | ;; :::::::::::::::::::: | |
1871 | ||
1872 | (define_expand "call" | |
1873 | [(parallel [(call (match_operand:QI 0 "" "") | |
1874 | (match_operand:SI 1 "" "")) | |
1875 | (use (match_operand:SI 2 "" "")) | |
1876 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1877 | ])] | |
1878 | "" | |
1879 | " | |
1880 | { | |
1881 | mep_expand_call (operands, 0); | |
1882 | DONE; | |
1883 | }") | |
1884 | ||
1885 | (define_insn "call_internal" | |
1886 | [(call (mem (match_operand:SI 0 "mep_call_address_operand" "R,r")) | |
1887 | (match_operand:SI 1 "" "")) | |
1888 | (use (match_operand:SI 2 "const_int_operand" "")) | |
1889 | (use (match_operand:SI 3 "mep_tp_operand" "b,b")) | |
1890 | (use (match_operand:SI 4 "mep_gp_operand" "v,v")) | |
1891 | (clobber (reg:SI LP_REGNO)) | |
1892 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1893 | ] | |
1894 | "" | |
1895 | { | |
1896 | static char const pattern[2][2][8] = | |
1897 | { | |
1898 | { "bsrv\t%0", "jsrv\t%0" }, | |
1899 | { "bsr\t%0", "jsr\t%0" } | |
1900 | }; | |
1901 | ||
1902 | return pattern[mep_vliw_mode_match (operands[2])][which_alternative]; | |
1903 | } | |
1904 | [(set_attr "length" "4,2")]) | |
1905 | ||
1906 | (define_expand "sibcall" | |
1907 | [(parallel [(call (match_operand:QI 0 "" "") | |
1908 | (match_operand:SI 1 "" "")) | |
1909 | (use (match_operand:SI 2 "" "")) | |
1910 | (use (reg:SI LP_REGNO)) | |
1911 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1912 | ])] | |
1913 | "" | |
1914 | "") | |
1915 | ||
1916 | (define_insn "*sibcall_internal" | |
1917 | [(call (mem (match_operand:SI 0 "mep_nearsym_operand" "s")) | |
1918 | (match_operand:SI 1 "" "")) | |
1919 | (use (match_operand:SI 2 "const_int_operand" "")) | |
1920 | (use (reg:SI LP_REGNO)) | |
1921 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1922 | ] | |
1923 | "SIBLING_CALL_P (insn)" | |
1924 | { | |
a9d1723f | 1925 | if (mep_vliw_jmp_match (operands[2])) |
7acf4da6 | 1926 | return "jmp\t%0"; |
54a1e1d0 DD |
1927 | else if (mep_vliw_mode_match (operands[2])) |
1928 | return | |
11af2d7b DD |
1929 | "movu $0, %0\n\ |
1930 | jmp $0"; | |
7acf4da6 DD |
1931 | else |
1932 | return | |
1933 | "ldc $12, $lp\n\ | |
1934 | movh $11, %%hi(%0)\n\ | |
1935 | xor3 $12, $12, 1\n\ | |
1936 | add3 $11, $11, %%lo(%0+1)\n\ | |
1937 | stc $12, $lp\n\ | |
1938 | jmp $11"; | |
1939 | } | |
1940 | [(set_attr "length" "48") | |
1941 | (set_attr "slot" "multi")]) | |
1942 | ||
1943 | (define_expand "call_value" | |
1944 | [(parallel [(set (match_operand 0 "" "") | |
1945 | (call (match_operand:QI 1 "" "") | |
1946 | (match_operand:SI 2 "" ""))) | |
1947 | (use (match_operand:SI 3 "" "")) | |
1948 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1949 | ])] | |
1950 | "" | |
1951 | " | |
1952 | { | |
1953 | mep_expand_call (operands, 1); | |
1954 | DONE; | |
1955 | }") | |
1956 | ||
1957 | (define_insn "call_value_internal" | |
1958 | [(set (match_operand 0 "register_operand" "=rx,rx") | |
1959 | (call (mem:SI (match_operand:SI 1 "mep_call_address_operand" "R,r")) | |
1960 | (match_operand:SI 2 "" ""))) | |
1961 | (use (match_operand:SI 3 "const_int_operand" "")) | |
1962 | (use (match_operand:SI 4 "mep_tp_operand" "b,b")) | |
1963 | (use (match_operand:SI 5 "mep_gp_operand" "v,v")) | |
1964 | (clobber (reg:SI LP_REGNO)) | |
1965 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1966 | ] | |
1967 | "" | |
1968 | { | |
1969 | static char const pattern[2][2][8] = | |
1970 | { | |
1971 | { "bsrv\t%1", "jsrv\t%1" }, | |
1972 | { "bsr\t%1", "jsr\t%1" } | |
1973 | }; | |
1974 | ||
1975 | return pattern[mep_vliw_mode_match (operands[3])][which_alternative]; | |
1976 | } | |
1977 | [(set_attr "length" "4,2")]) | |
1978 | ||
1979 | (define_expand "sibcall_value" | |
1980 | [(parallel [(set (match_operand 0 "" "") | |
1981 | (call (match_operand:QI 1 "" "") | |
1982 | (match_operand:SI 2 "" ""))) | |
1983 | (use (match_operand:SI 3 "" "")) | |
1984 | (use (reg:SI LP_REGNO)) | |
1985 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1986 | ])] | |
1987 | "" | |
1988 | "") | |
1989 | ||
1990 | (define_insn "*sibcall_value_internal" | |
1991 | [(set (match_operand 0 "register_operand" "=rx") | |
1992 | (call (mem (match_operand:SI 1 "mep_nearsym_operand" "s")) | |
1993 | (match_operand:SI 2 "" ""))) | |
1994 | (use (match_operand:SI 3 "const_int_operand" "")) | |
1995 | (use (reg:SI LP_REGNO)) | |
1996 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1997 | ] | |
1998 | "SIBLING_CALL_P (insn)" | |
1999 | { | |
a9d1723f | 2000 | if (mep_vliw_jmp_match (operands[3])) |
7acf4da6 | 2001 | return "jmp\t%1"; |
54a1e1d0 DD |
2002 | else if (mep_vliw_mode_match (operands[3])) |
2003 | return | |
11af2d7b DD |
2004 | "movu $0, %1\n\ |
2005 | jmp $0"; | |
7acf4da6 DD |
2006 | else |
2007 | return | |
2008 | "ldc $12, $lp\n\ | |
2009 | movh $11, %%hi(%1)\n\ | |
2010 | xor3 $12, $12, 1\n\ | |
2011 | add3 $11, $11, %%lo(%1+1)\n\ | |
2012 | stc $12, $lp\n\ | |
2013 | jmp $11"; | |
2014 | } | |
2015 | [(set_attr "length" "48") | |
2016 | (set_attr "slot" "multi")]) | |
2017 | ||
2018 | (define_insn "return_internal" | |
2019 | [(return) | |
2020 | (use (match_operand:SI 0 "register_operand" ""))] | |
2021 | "" | |
2022 | "* return (REGNO (operands[0]) == LP_REGNO) ? \"ret\" : \"jmp\\t%0\";" | |
2023 | [(set_attr "length" "2") | |
2024 | (set_attr "stall" "ret")]) | |
2025 | ||
2026 | (define_insn "eh_return_internal" | |
2027 | [(return) | |
2028 | (use (reg:SI 10)) | |
2029 | (use (reg:SI 11)) | |
2030 | (use (reg:SI LP_REGNO)) | |
2031 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
2032 | ] | |
2033 | "" | |
2034 | "ret" | |
2035 | [(set_attr "length" "2") | |
2036 | (set_attr "stall" "ret")]) | |
2037 | ||
2038 | ;; The assembler replaces short jumps with long jumps as needed. | |
2039 | (define_insn "jump" | |
2040 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
2041 | "" | |
2042 | "bra\\t%l0" | |
2043 | [(set_attr "length" "4")]) | |
2044 | ||
2045 | (define_insn "indirect_jump" | |
2046 | [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
2047 | "" | |
2048 | "jmp\\t%0" | |
2049 | [(set_attr "length" "2")]) | |
2050 | ||
2051 | (define_insn "tablejump" | |
2052 | [(set (pc) (match_operand:SI 0 "register_operand" "r")) | |
2053 | (use (label_ref (match_operand 1 "" "")))] | |
2054 | "" | |
2055 | "jmp\\t%0" | |
2056 | [(set_attr "length" "2")]) | |
2057 | ||
2058 | \f | |
2059 | ;; :::::::::::::::::::: | |
2060 | ;; :: | |
2061 | ;; :: Low Overhead Looping | |
2062 | ;; :: | |
2063 | ;; :::::::::::::::::::: | |
2064 | ||
2065 | ;; This insn is volatile because we'd like it to stay in its original | |
2066 | ;; position, just before the loop header. If it stays there, we might | |
2067 | ;; be able to convert it into a "repeat" insn. | |
2068 | (define_insn "doloop_begin_internal" | |
2069 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2070 | (unspec_volatile:SI | |
2071 | [(match_operand:SI 1 "register_operand" "0") | |
2072 | (match_operand 2 "const_int_operand" "")] UNS_REPEAT_BEG))] | |
2073 | "" | |
2074 | { gcc_unreachable (); } | |
2075 | [(set_attr "length" "4")]) | |
2076 | ||
2077 | (define_expand "doloop_begin" | |
2078 | [(use (match_operand 0 "register_operand" "")) | |
1d0216c8 | 2079 | (use (match_operand 1 "" ""))] |
7acf4da6 | 2080 | "!profile_arc_flag && TARGET_OPT_REPEAT" |
1d0216c8 | 2081 | "mep_emit_doloop (operands, 0); |
7acf4da6 DD |
2082 | DONE; |
2083 | ") | |
2084 | ||
2085 | (define_insn "doloop_end_internal" | |
2086 | [(set (pc) | |
2087 | (if_then_else (ne (match_operand:SI 0 "nonimmediate_operand" "+r,cxy,*m") | |
2088 | (const_int 0)) | |
2089 | (label_ref (match_operand 1 "" "")) | |
2090 | (pc))) | |
2091 | (set (match_dup 0) | |
2092 | (plus:SI (match_dup 0) | |
2093 | (const_int -1))) | |
2094 | (unspec [(match_operand 2 "const_int_operand" "")] UNS_REPEAT_END) | |
2095 | (clobber (match_scratch:SI 3 "=X,&r,&r"))] | |
2096 | "" | |
2097 | { gcc_unreachable (); } | |
2098 | ;; Worst case length: | |
2099 | ;; | |
2100 | ;; lw <op3>,<op0> 4 | |
2101 | ;; add <op3>,-1 2 | |
2102 | ;; sw <op3>,<op0> 4 | |
2103 | ;; jmp <op1> 4 | |
2104 | ;; 1f: | |
2105 | [(set_attr "length" "14") | |
2106 | (set_attr "slot" "multi")]) | |
2107 | ||
2108 | (define_expand "doloop_end" | |
2109 | [(use (match_operand 0 "nonimmediate_operand" "")) | |
1d0216c8 | 2110 | (use (label_ref (match_operand 1 "" "")))] |
7acf4da6 | 2111 | "!profile_arc_flag && TARGET_OPT_REPEAT" |
1d0216c8 | 2112 | "if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) != SImode) |
7acf4da6 DD |
2113 | FAIL; |
2114 | mep_emit_doloop (operands, 1); | |
2115 | DONE; | |
2116 | ") | |
2117 | ||
2118 | (define_insn "repeat" | |
2119 | [(set (reg:SI RPC_REGNO) | |
2120 | (unspec:SI [(match_operand:SI 0 "mep_r0_15_operand" "r") | |
2121 | (match_operand:SI 1 "" "")] | |
2122 | UNS_REPEAT_BEG))] | |
2123 | "" | |
2124 | "repeat\\t%0,%l1" | |
2125 | [(set_attr "length" "4")]) | |
2126 | ||
2127 | (define_insn "repeat_end" | |
2128 | [(unspec [(const_int 0)] UNS_REPEAT_END)] | |
2129 | "" | |
2130 | "# repeat end" | |
2131 | [(set_attr "length" "0")]) | |
2132 | ||
2133 | (define_insn "erepeat" | |
2134 | [(unspec [(match_operand 0 "" "")] UNS_EREPEAT_BEG)] | |
2135 | "" | |
2136 | "erepeat\\t%l0" | |
2137 | [(set_attr "length" "4")]) | |
2138 | ||
2139 | (define_insn "erepeat_end" | |
2140 | [(unspec [(const_int 0)] UNS_EREPEAT_END)] | |
2141 | "" | |
2142 | "# erepeat end" | |
2143 | [(set_attr "length" "0") | |
2144 | (set_attr "slot" "multi")]) | |
2145 | ||
2146 | \f | |
2147 | ;; :::::::::::::::::::: | |
2148 | ;; :: | |
2149 | ;; :: Prologue and Epilogue instructions | |
2150 | ;; :: | |
2151 | ;; :::::::::::::::::::: | |
2152 | ||
2153 | (define_expand "prologue" | |
2154 | [(const_int 1)] | |
2155 | "" | |
2156 | " | |
2157 | { | |
2158 | mep_expand_prologue (); | |
2159 | DONE; | |
2160 | }") | |
2161 | ||
2162 | (define_expand "epilogue" | |
2163 | [(return)] | |
2164 | "" | |
2165 | " | |
2166 | { | |
2167 | mep_expand_epilogue (); | |
2168 | DONE; | |
2169 | }") | |
2170 | ||
2171 | (define_expand "eh_return" | |
2172 | [(use (match_operand:SI 0 "register_operand" "r"))] | |
2173 | "" | |
2174 | " | |
2175 | { | |
2176 | mep_expand_eh_return (operands); | |
2177 | DONE; | |
2178 | }") | |
2179 | ||
2180 | (define_insn_and_split "eh_epilogue" | |
2181 | [(unspec [(match_operand:SI 0 "register_operand" "r")] UNS_EH_EPILOGUE) | |
2182 | (use (reg:SI LP_REGNO))] | |
2183 | "" | |
2184 | "#" | |
5ba863d7 | 2185 | "epilogue_completed" |
7acf4da6 DD |
2186 | [(const_int 1)] |
2187 | "mep_emit_eh_epilogue (operands); DONE;" | |
2188 | [(set_attr "slot" "multi")]) | |
2189 | ||
2190 | (define_expand "sibcall_epilogue" | |
2191 | [(const_int 0)] | |
2192 | "" | |
2193 | " | |
2194 | { | |
2195 | mep_expand_sibcall_epilogue (); | |
2196 | DONE; | |
2197 | }") | |
2198 | ||
2199 | (define_insn "mep_bb_trace_ret" | |
2200 | [(unspec_volatile [(const_int 0)] UNS_BB_TRACE_RET)] | |
2201 | "" | |
2202 | "* return mep_emit_bb_trace_ret ();" | |
2203 | [(set_attr "slot" "multi")]) | |
2204 | ||
2205 | (define_insn "mep_disable_int" | |
2206 | [(unspec_volatile [(const_int 0)] UNS_DISABLE_INT)] | |
2207 | "" | |
2208 | "di" | |
2209 | [(set_attr "length" "2")]) | |
2210 | ||
2211 | (define_insn "mep_enable_int" | |
2212 | [(unspec_volatile [(const_int 0)] UNS_ENABLE_INT)] | |
2213 | "" | |
2214 | "ei" | |
2215 | [(set_attr "length" "2")]) | |
2216 | ||
2217 | (define_insn "mep_reti" | |
2218 | [(return) | |
2219 | (unspec_volatile [(const_int 0)] UNS_RETI)] | |
2220 | "" | |
2221 | "reti" | |
2222 | [(set_attr "length" "2")]) | |
2223 | \f | |
2224 | ;; :::::::::::::::::::: | |
2225 | ;; :: | |
2226 | ;; :: Miscellaneous instructions | |
2227 | ;; :: | |
2228 | ;; :::::::::::::::::::: | |
2229 | ||
2230 | (define_insn "nop" | |
2231 | [(const_int 0)] | |
2232 | "" | |
2233 | "nop" | |
2234 | [(set_attr "length" "2")]) | |
2235 | ||
2236 | (define_insn "nop32" | |
2237 | [(const_int 1)] | |
2238 | "" | |
2239 | "or3\\t$0, $0, 0" | |
2240 | [(set_attr "length" "4")]) | |
2241 | ||
2242 | (define_insn "blockage" | |
2243 | [(unspec_volatile [(const_int 0)] UNS_BLOCKAGE)] | |
2244 | "" | |
2245 | "" | |
2246 | [(set_attr "length" "0") | |
2247 | (set_attr "slot" "multi")]) | |
2248 | ||
2249 | ||
2250 | (define_insn "djmark" | |
2251 | [(unspec_volatile [(const_int 0)] 999)] | |
2252 | "" | |
2253 | "# dj" | |
2254 | [(set_attr "length" "0") | |
2255 | (set_attr "slot" "multi")]) | |
2256 |