]>
Commit | Line | Data |
---|---|---|
46222c18 | 1 | ;; Toshiba Media Processor Machine description template |
f1717362 | 2 | ;; Copyright (C) 2001-2016 Free Software Foundation, Inc. |
46222c18 | 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 | { | |
46222c18 | 763 | HOST_WIDE_INT value; |
764 | HOST_WIDE_INT lo, hi; | |
765 | rtx out; | |
766 | ||
945f7b03 | 767 | REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), value); |
46222c18 | 768 | |
769 | lo = value & 0xffff; | |
770 | hi = trunc_int_for_mode (value & 0xffff0000, SImode); | |
771 | ||
772 | out = gen_rtx_REG (SImode, REGNO (operands[0])); | |
773 | emit_move_insn (out, GEN_INT (hi)); | |
774 | if (lo != 0) | |
775 | emit_insn (gen_iorsi3 (out, out, GEN_INT (lo))); | |
776 | DONE; | |
777 | }") | |
778 | ||
779 | (define_expand "movdf" | |
780 | [(set (match_operand:DF 0 "" "") | |
781 | (match_operand:DF 1 "" ""))] | |
782 | "" | |
783 | " | |
784 | { | |
785 | if (mep_expand_mov (operands, DFmode)) | |
786 | DONE; | |
787 | }") | |
788 | ||
789 | (define_insn "*movdf_internal_32" | |
790 | [(set (match_operand:DF 0 "mep_movdest_operand" "= r,m,r,c,r,er,ex,em,U") | |
791 | (match_operand:DF 1 "general_operand" "rFm,r,c,r,er,r,ex,U,em"))] | |
792 | "TARGET_32BIT_CR_REGS && mep_mov_ok (operands, DFmode)" | |
793 | "#" | |
794 | [(set_attr "slot" "multi")]) | |
795 | ||
796 | (define_insn "*movdf_internal_64" | |
797 | [(set (match_operand:DF 0 "mep_movdest_operand" "= r,m,r,c,r,er,ex,em,U") | |
798 | (match_operand:DF 1 "general_operand" "rFm,r,c,r,er,r,ex,U,em"))] | |
799 | "TARGET_64BIT_CR_REGS && mep_mov_ok (operands, DFmode)" | |
800 | "@ | |
801 | # | |
802 | # | |
803 | # | |
804 | # | |
805 | # | |
806 | # | |
807 | %<\\t%0, %M1 | |
808 | lmcp\\t%0, %1 | |
809 | smcp\\t%1, %0" | |
810 | [(set_attr "slot" "multi,multi,multi,multi,multi,multi,*,*,*") | |
811 | (set_attr "intrinsic" "*,*,*,*,*,*,cmov,*,*") | |
812 | (set_attr "memop" "*,*,*,*,*,*,*,cop1,cop0") | |
813 | (set_attr "stall" "*,*,*,*,*,*,*,load,store")]) | |
814 | ||
815 | (define_split | |
816 | [(set (match_operand:DF 0 "mep_movdest_operand" "") | |
817 | (match_operand:DF 1 "general_operand" ""))] | |
818 | "reload_completed && mep_multi_slot (insn)" | |
819 | [(set (match_dup 2) (match_dup 3)) | |
820 | (set (match_dup 4) (match_dup 5))] | |
821 | "mep_split_wide_move (operands, DFmode);") | |
822 | ||
823 | \f | |
824 | (define_insn "*lbcpa" | |
825 | [(set (match_operand:SI 0 "register_operand" "=em") | |
826 | (sign_extend:SI (mem:QI (match_operand:SI 2 "register_operand" "1")))) | |
827 | (set (match_operand:SI 1 "register_operand" "=r") | |
828 | (plus:SI (match_dup 2) | |
829 | (match_operand:SI 3 "cgen_h_sint_8a1_immediate" "")))] | |
830 | "TARGET_COP && reload_completed" | |
831 | "lbcpa\t%0, (%1+), %3" | |
832 | [(set_attr "length" "4") | |
833 | (set_attr "stall" "load")]) | |
834 | ||
835 | (define_insn "*sbcpa" | |
836 | [(set (mem:QI (match_operand:SI 1 "register_operand" "0")) | |
837 | (match_operand:QI 2 "register_operand" "em")) | |
838 | (set (match_operand:SI 0 "register_operand" "=r") | |
839 | (plus:SI (match_dup 1) | |
840 | (match_operand:SI 3 "cgen_h_sint_8a1_immediate" "")))] | |
841 | "TARGET_COP && reload_completed" | |
842 | "sbcpa\t%2, (%0+), %3" | |
843 | [(set_attr "length" "4") | |
844 | (set_attr "stall" "store")]) | |
845 | ||
846 | (define_insn "*lhcpa" | |
847 | [(set (match_operand:SI 0 "register_operand" "=em") | |
848 | (sign_extend:SI (mem:HI (match_operand:SI 2 "register_operand" "1")))) | |
849 | (set (match_operand:SI 1 "register_operand" "=r") | |
850 | (plus:SI (match_dup 2) | |
851 | (match_operand:SI 3 "cgen_h_sint_7a2_immediate" "")))] | |
852 | "TARGET_COP && reload_completed" | |
853 | "lhcpa\t%0, (%1+), %3" | |
854 | [(set_attr "length" "4") | |
855 | (set_attr "stall" "load")]) | |
856 | ||
857 | (define_insn "*shcpa" | |
858 | [(set (mem:HI (match_operand:SI 1 "register_operand" "0")) | |
859 | (match_operand:HI 2 "register_operand" "em")) | |
860 | (set (match_operand:SI 0 "register_operand" "=r") | |
861 | (plus:SI (match_dup 1) | |
862 | (match_operand:SI 3 "cgen_h_sint_7a2_immediate" "")))] | |
863 | "TARGET_COP && reload_completed" | |
864 | "shcpa\t%2, (%0+), %3" | |
865 | [(set_attr "length" "4") | |
866 | (set_attr "stall" "store")]) | |
867 | ||
868 | (define_insn "*lwcpi" | |
869 | [(set (match_operand:SI 0 "register_operand" "=em") | |
870 | (mem:SI (match_operand:SI 2 "register_operand" "1"))) | |
871 | (set (match_operand:SI 1 "register_operand" "=r") | |
872 | (plus:SI (match_dup 2) | |
873 | (const_int 4)))] | |
874 | "TARGET_COP && reload_completed" | |
875 | "lwcpi\t%0, (%1+)" | |
876 | [(set_attr "length" "2") | |
877 | (set_attr "stall" "load")]) | |
878 | ||
879 | (define_insn "*lwcpa" | |
880 | [(set (match_operand:SI 0 "register_operand" "=em") | |
881 | (mem:SI (match_operand:SI 2 "register_operand" "1"))) | |
882 | (set (match_operand:SI 1 "register_operand" "=r") | |
883 | (plus:SI (match_dup 2) | |
884 | (match_operand:SI 3 "cgen_h_sint_6a4_immediate" "")))] | |
885 | "TARGET_COP && reload_completed" | |
886 | "lwcpa\t%0, (%1+), %3" | |
887 | [(set_attr "length" "4") | |
888 | (set_attr "stall" "load")]) | |
889 | ||
890 | (define_insn "*swcpi" | |
891 | [(set (mem:SI (match_operand:SI 1 "register_operand" "0")) | |
892 | (match_operand:SI 2 "register_operand" "em")) | |
893 | (set (match_operand:SI 0 "register_operand" "=r") | |
894 | (plus:SI (match_dup 1) | |
895 | (const_int 4)))] | |
896 | "TARGET_COP && reload_completed" | |
897 | "swcpi\t%2, (%0+)" | |
898 | [(set_attr "length" "2") | |
899 | (set_attr "stall" "store")]) | |
900 | ||
901 | (define_insn "*swcpa" | |
902 | [(set (mem:SI (match_operand:SI 1 "register_operand" "0")) | |
903 | (match_operand:SI 2 "register_operand" "em")) | |
904 | (set (match_operand:SI 0 "register_operand" "=r") | |
905 | (plus:SI (match_dup 1) | |
906 | (match_operand:SI 3 "cgen_h_sint_6a4_immediate" "")))] | |
907 | "TARGET_COP && reload_completed" | |
908 | "swcpa\t%2, (%0+), %3" | |
909 | [(set_attr "length" "4") | |
910 | (set_attr "stall" "store")]) | |
911 | ||
912 | (define_peephole2 | |
913 | [(set (match_operand:SI 0 "register_operand" "") | |
914 | (plus:SI (match_dup 0) | |
915 | (match_operand:SI 1 "cgen_h_sint_8a1_immediate" "")))] | |
916 | "TARGET_COP && mep_use_post_modify_p (insn, operands[0], operands[1])" | |
917 | [(const_int 0)] | |
918 | { | |
919 | emit_note (NOTE_INSN_DELETED); | |
920 | DONE; | |
921 | }) | |
922 | \f | |
923 | ;; :::::::::::::::::::: | |
924 | ;; :: | |
925 | ;; :: Reloads | |
926 | ;; :: | |
927 | ;; :::::::::::::::::::: | |
928 | ||
929 | (define_expand "reload_insi" | |
930 | [(set (match_operand:SI 0 "mep_reload_operand" "") | |
931 | (match_operand:SI 1 "mep_reload_operand" "r")) | |
932 | (clobber (match_operand:SI 2 "register_operand" "=&r"))] | |
933 | "" | |
934 | " | |
935 | { | |
936 | mep_expand_reload (operands, SImode); | |
937 | DONE; | |
938 | }") | |
939 | ||
940 | (define_expand "reload_outsi" | |
941 | [(set (match_operand:SI 0 "mep_reload_operand" "=r") | |
942 | (match_operand:SI 1 "mep_reload_operand" "")) | |
943 | (clobber (match_operand:SI 2 "register_operand" "=&r"))] | |
944 | "" | |
945 | " | |
946 | { | |
947 | mep_expand_reload (operands, SImode); | |
948 | DONE; | |
949 | }") | |
950 | ||
951 | \f | |
952 | ;; :::::::::::::::::::: | |
953 | ;; :: | |
954 | ;; :: Conversions | |
955 | ;; :: | |
956 | ;; :::::::::::::::::::: | |
957 | ||
958 | (define_insn "extendqisi2" | |
959 | [(set (match_operand:SI 0 "register_operand" "=r,r,em") | |
960 | (sign_extend:SI | |
961 | (match_operand:QI 1 "nonimmediate_operand" "0,m,Y")))] | |
962 | "" | |
963 | "@ | |
964 | extb\\t%0 | |
965 | lb\\t%0, %1 | |
966 | lbcpa\\t%0, %P1" | |
967 | [(set_attr "length" "2,*,*") | |
968 | (set_attr "stall" "*,load,load") | |
969 | (set_attr "memop" "*,core1,cop1")]) | |
970 | ||
971 | (define_insn "extendhisi2" | |
972 | [(set (match_operand:SI 0 "register_operand" "=r,r,em") | |
973 | (sign_extend:SI | |
974 | (match_operand:HI 1 "nonimmediate_operand" "0,m,Y")))] | |
975 | "" | |
976 | "@ | |
977 | exth\\t%0 | |
978 | lh\\t%0, %1 | |
979 | lhcpa\\t%0, %P1" | |
980 | [(set_attr "length" "2,*,*") | |
981 | (set_attr "stall" "*,load,load") | |
982 | (set_attr "memop" "*,core1,cop1")]) | |
983 | ||
984 | (define_insn "zero_extendqisi2" | |
985 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
986 | (zero_extend:SI | |
987 | (match_operand:QI 1 "nonimmediate_operand" "0,r,m")))] | |
988 | "" | |
989 | "@ | |
990 | extub\\t%0 | |
991 | and3\\t%0, %1, 255 | |
992 | lbu\\t%0, %1" | |
993 | [(set_attr "length" "2,4,*") | |
994 | (set_attr "stall" "*,*,load") | |
995 | (set_attr "memop" "*,*,core1")]) | |
996 | ||
997 | (define_insn "zero_extendhisi2" | |
998 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
999 | (zero_extend:SI | |
1000 | (match_operand:HI 1 "nonimmediate_operand" "0,r,m")))] | |
1001 | "" | |
1002 | "@ | |
1003 | extuh\\t%0 | |
1004 | and3\\t%0, %1, 65535 | |
1005 | lhu\\t%0, %1" | |
1006 | [(set_attr "length" "2,4,*") | |
1007 | (set_attr "stall" "*,*,load") | |
1008 | (set_attr "memop" "*,*,core1")]) | |
1009 | \f | |
1010 | ;; :::::::::::::::::::: | |
1011 | ;; :: | |
1012 | ;; :: 32 bit Integer arithmetic | |
1013 | ;; :: | |
1014 | ;; :::::::::::::::::::: | |
1015 | ||
1016 | (define_insn "addsi3" | |
1017 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1018 | (plus:SI (match_operand:SI 1 "register_operand" "%r,0,r") | |
1019 | (match_operand:SI 2 "mep_add_operand" "r,L,IT")))] | |
1020 | "" | |
1021 | "@ | |
1022 | add3\\t%0, %1, %2 | |
1023 | add\\t%0, %2 | |
1024 | add3\\t%0, %1, %I2" | |
1025 | [(set (attr "length") | |
1026 | (if_then_else (eq_attr "alternative" "2") | |
1027 | (if_then_else (and (match_operand:SI 1 "mep_sp_operand" "") | |
1028 | (match_operand:SI 2 "mep_imm7a4_operand" "")) | |
1029 | (const_int 2) | |
1030 | (const_int 4)) | |
1031 | (const_int 2)))]) | |
1032 | ||
1033 | ;; The intention here is to combine the 16-bit add with the 16-bit | |
1034 | ;; move to create a 32-bit add. It's the same size, but takes one | |
1035 | ;; less machine cycle. It will happen to match a 32-bit add with a | |
1036 | ;; 16-bit move also, but gcc shouldn't be doing that ;) | |
1037 | (define_peephole2 | |
1038 | [(set (match_operand:SI 0 "register_operand" "") | |
1039 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
1040 | (match_operand:SI 2 "immediate_operand" ""))) | |
1041 | (set (match_operand:SI 3 "register_operand" "") | |
1042 | (match_operand:SI 4 "register_operand" ""))] | |
1043 | "REGNO (operands[0]) == REGNO (operands[1]) | |
1044 | && REGNO (operands[0]) == REGNO (operands[4]) | |
1045 | && GR_REGNO_P (REGNO (operands[3])) | |
1046 | && dead_or_set_p (peep2_next_insn (1), operands[4])" | |
1047 | [(set (match_dup 3) | |
1048 | (plus:SI (match_dup 1) | |
1049 | (match_dup 2)))] | |
1050 | "") | |
1051 | ||
1052 | (define_insn "subsi3" | |
1053 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1054 | (minus:SI (match_operand:SI 1 "register_operand" "0") | |
1055 | (match_operand:SI 2 "register_operand" "r")))] | |
1056 | "" | |
1057 | "sub\\t%0, %2" | |
1058 | [(set_attr "length" "2")]) | |
1059 | ||
1060 | (define_expand "mulsi3" | |
1061 | [(set (match_operand:SI 0 "register_operand" "") | |
1062 | (mult:SI (match_operand:SI 1 "register_operand" "") | |
1063 | (match_operand:SI 2 "register_operand" "")))] | |
1064 | "TARGET_OPT_MULT || TARGET_COPRO_MULT" | |
1065 | { | |
1066 | emit_insn (gen_mulsi3_1 (operands[0], operands[1], operands[2])); | |
1067 | DONE; | |
1068 | }) | |
1069 | ||
1070 | ;; Generated by mep_reuse_lo_p when no GPR destination is needed. | |
1071 | (define_insn "mulsi3_lo" | |
1072 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1073 | (mult:SI (match_operand:SI 1 "register_operand" "r") | |
1074 | (match_operand:SI 2 "register_operand" "r"))) | |
1075 | (clobber (match_scratch:SI 3 "=h"))] | |
1076 | "TARGET_OPT_MULT && reload_completed" | |
1077 | "mul\\t%1, %2" | |
1078 | [(set_attr "length" "2") | |
1079 | (set_attr "stall" "mul")]) | |
1080 | ||
1081 | ;; Generated by mep_reuse_lo_p when both destinations of a mulr | |
1082 | ;; are needed. | |
1083 | (define_insn "mulsi3r" | |
1084 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1085 | (mult:SI (match_operand:SI 2 "register_operand" "1") | |
1086 | (match_operand:SI 3 "register_operand" "r"))) | |
1087 | (set (match_operand:SI 1 "register_operand" "=r") | |
1088 | (mult:SI (match_dup 2) | |
1089 | (match_dup 3))) | |
1090 | (clobber (match_scratch:SI 4 "=h"))] | |
1091 | "TARGET_OPT_MULT && reload_completed" | |
1092 | "mulr\\t%2, %3" | |
1093 | [(set_attr "length" "2") | |
1094 | (set_attr "stall" "mulr")]) | |
1095 | ||
1096 | (define_insn "mulsi3_1" | |
1097 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1098 | (mult:SI (match_operand:SI 1 "register_operand" "%0") | |
1099 | (match_operand:SI 2 "register_operand" "r"))) | |
1100 | (clobber (match_scratch:SI 3 "=l")) | |
1101 | (clobber (match_scratch:SI 4 "=h"))] | |
1102 | "TARGET_OPT_MULT" | |
1103 | "mulr\\t%1, %2" | |
1104 | [(set_attr "length" "2") | |
1105 | (set_attr "stall" "mulr")]) | |
1106 | ||
1107 | (define_expand "mulsidi3" | |
1108 | [(set (match_operand:DI 0 "register_operand" "") | |
1109 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) | |
1110 | (sign_extend:DI (match_operand:SI 2 "register_operand" ""))))] | |
1111 | "TARGET_OPT_MULT" | |
1112 | " | |
1113 | { | |
1114 | rtx hi = gen_reg_rtx (SImode); | |
1115 | rtx lo = gen_reg_rtx (SImode); | |
1116 | ||
1117 | emit_insn (gen_mulsidi3_i (hi, lo, operands[1], operands[2])); | |
1118 | emit_move_insn (gen_lowpart (SImode, operands[0]), lo); | |
1119 | emit_move_insn (gen_highpart (SImode, operands[0]), hi); | |
1120 | DONE; | |
1121 | }") | |
1122 | ||
1123 | (define_insn "mulsidi3_i" | |
1124 | [(set (match_operand:SI 0 "mep_hi_operand" "=h") | |
1125 | (truncate:SI | |
1126 | (lshiftrt:DI | |
1127 | (mult:DI (sign_extend:DI | |
1128 | (match_operand:SI 2 "register_operand" "r")) | |
1129 | (sign_extend:DI | |
1130 | (match_operand:SI 3 "register_operand" "r"))) | |
1131 | (const_int 32)))) | |
1132 | (set (match_operand:SI 1 "mep_lo_operand" "=l") | |
1133 | (mult:SI (match_dup 2) | |
1134 | (match_dup 3)))] | |
1135 | "TARGET_OPT_MULT" | |
1136 | "mul\\t%2, %3" | |
1137 | [(set_attr "length" "2") | |
1138 | (set_attr "stall" "mul")]) | |
1139 | ||
1140 | (define_insn "smulsi3_highpart" | |
1141 | [(set (match_operand:SI 0 "mep_hi_operand" "=h") | |
1142 | (truncate:SI | |
1143 | (lshiftrt:DI | |
1144 | (mult:DI (sign_extend:DI | |
1145 | (match_operand:SI 1 "register_operand" "r")) | |
1146 | (sign_extend:DI | |
1147 | (match_operand:SI 2 "register_operand" "r"))) | |
1148 | (const_int 32)))) | |
1149 | (clobber (reg:SI LO_REGNO))] | |
1150 | "TARGET_OPT_MULT" | |
1151 | "mul\\t%1, %2" | |
1152 | [(set_attr "length" "2") | |
1153 | (set_attr "stall" "mul")]) | |
1154 | ||
1155 | (define_expand "umulsidi3" | |
1156 | [(set (match_operand:DI 0 "mep_hi_operand" "") | |
1157 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) | |
1158 | (zero_extend:DI (match_operand:SI 2 "register_operand" ""))))] | |
1159 | "TARGET_OPT_MULT" | |
1160 | " | |
1161 | { | |
1162 | rtx hi = gen_reg_rtx (SImode); | |
1163 | rtx lo = gen_reg_rtx (SImode); | |
1164 | ||
1165 | emit_insn (gen_umulsidi3_i (hi, lo, operands[1], operands[2])); | |
1166 | emit_move_insn (gen_lowpart (SImode, operands[0]), lo); | |
1167 | emit_move_insn (gen_highpart (SImode, operands[0]), hi); | |
1168 | DONE; | |
1169 | }") | |
1170 | ||
1171 | (define_insn "umulsidi3_i" | |
1172 | [(set (match_operand:SI 0 "mep_hi_operand" "=h") | |
1173 | (truncate:SI | |
1174 | (lshiftrt:DI | |
1175 | (mult:DI (zero_extend:DI | |
1176 | (match_operand:SI 2 "register_operand" "r")) | |
1177 | (zero_extend:DI | |
1178 | (match_operand:SI 3 "register_operand" "r"))) | |
1179 | (const_int 32)))) | |
1180 | (set (match_operand:SI 1 "mep_lo_operand" "=l") | |
1181 | (mult:SI (match_dup 2) | |
1182 | (match_dup 3)))] | |
1183 | "TARGET_OPT_MULT" | |
1184 | "mulu\\t%2, %3" | |
1185 | [(set_attr "length" "2") | |
1186 | (set_attr "stall" "mul")]) | |
1187 | ||
1188 | (define_insn "umulsi3_highpart" | |
1189 | [(set (match_operand:SI 0 "mep_hi_operand" "=h") | |
1190 | (truncate:SI | |
1191 | (lshiftrt:DI | |
1192 | (mult:DI (zero_extend:DI | |
1193 | (match_operand:SI 1 "register_operand" "r")) | |
1194 | (zero_extend:DI | |
1195 | (match_operand:SI 2 "register_operand" "r"))) | |
1196 | (const_int 32)))) | |
1197 | (clobber (reg:SI LO_REGNO))] | |
1198 | "TARGET_OPT_MULT" | |
1199 | "mulu %1, %2" | |
1200 | [(set_attr "length" "2") | |
1201 | (set_attr "stall" "mul")]) | |
1202 | ||
1203 | ;; These two don't currently match because we don't have an adddi3 pattern. | |
1204 | (define_insn "*smultdi_and_add" | |
1205 | [(set (match_operand:DI 0 "mep_hi_operand" "=d") | |
1206 | (plus:DI (mult:DI (zero_extend:DI | |
1207 | (match_operand:SI 1 "register_operand" "r")) | |
1208 | (zero_extend:DI | |
1209 | (match_operand:SI 2 "register_operand" "r"))) | |
1210 | (match_operand:DI 3 "mep_hi_operand" "0")))] | |
1211 | "TARGET_OPT_MULT && TARGET_BIG_ENDIAN" | |
1212 | "maddu\\t%1, %2" | |
1213 | [(set_attr "length" "4") | |
1214 | (set_attr "stall" "mul")]) | |
1215 | ||
1216 | (define_insn "*umultdi_and_add" | |
1217 | [(set (match_operand:DI 0 "mep_hi_operand" "=d") | |
1218 | (plus:DI (mult:DI (sign_extend:DI | |
1219 | (match_operand:SI 1 "register_operand" "r")) | |
1220 | (sign_extend:DI | |
1221 | (match_operand:SI 2 "register_operand" "r"))) | |
1222 | (match_operand:DI 3 "mep_hi_operand" "0")))] | |
1223 | "TARGET_OPT_MULT && TARGET_BIG_ENDIAN" | |
1224 | "madd\\t%1, %2" | |
1225 | [(set_attr "length" "4") | |
1226 | (set_attr "stall" "mul")]) | |
1227 | ||
1228 | ;; A pattern for 'r1 = r2 * r3 + r4'. There are three possible | |
1229 | ;; implementations: | |
1230 | ;; | |
1231 | ;; (1) 'mulr;add3'. This is usually the best choice if the instruction | |
1232 | ;; is not part of a natural multiply-accumulate chain. It has the | |
1233 | ;; same latency as 'stc;maddr' but doesn't tie up $lo for as long. | |
1234 | ;; | |
1235 | ;; (2) 'madd'. This is the best choice if the instruction is in the | |
1236 | ;; middle of a natural multiply-accumulate chain. r4 will already | |
1237 | ;; be in $lo and r1 will also be needed in $lo. | |
1238 | ;; | |
1239 | ;; (3) 'maddr'. This is the best choice if the instruction is at the | |
1240 | ;; end of a natural multiply-accumulate chain. r4 will be in $lo | |
1241 | ;; but r1 will be needed in a GPR. | |
1242 | ;; | |
1243 | ;; In theory, we could put all the alternatives into a single pattern and | |
1244 | ;; leave the register allocator to choose between them. However, this can | |
1245 | ;; sometimes produce poor results in practice. | |
1246 | ;; | |
1247 | ;; This pattern therefore describes a general GPR-to-GPR operation that | |
1248 | ;; has a slight preference for cases in which operands 0 and 1 are tied. | |
1249 | ;; After reload, we try to rewrite the patterns using peephole2s (if | |
1250 | ;; enabled), falling back on define_splits if that fails. See also | |
1251 | ;; mep_reuse_lo_p. | |
1252 | (define_insn "maddsi3" | |
1253 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1254 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%0,r") | |
1255 | (match_operand:SI 2 "register_operand" "r,r")) | |
1256 | (match_operand:SI 3 "register_operand" "r,r"))) | |
1257 | (clobber (match_scratch:SI 4 "=l,l")) | |
1258 | (clobber (match_scratch:SI 5 "=h,h"))] | |
1259 | "TARGET_OPT_MULT" | |
1260 | "#" | |
1261 | [(set_attr "length" "8") | |
1262 | (set_attr "stall" "mulr")]) | |
1263 | ||
1264 | ;; Implement maddsi3s using maddr if operand 3 is already available in $lo. | |
1265 | (define_peephole2 | |
1266 | [(parallel | |
1267 | [(set (match_operand:SI 0 "register_operand" "") | |
1268 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") | |
1269 | (match_operand:SI 2 "register_operand" "")) | |
1270 | (match_operand:SI 3 "register_operand" ""))) | |
1271 | (clobber (match_scratch:SI 4 "")) | |
1272 | (clobber (match_scratch:SI 5 ""))])] | |
1273 | "TARGET_OPT_MULT | |
1274 | && reload_completed | |
1275 | && mep_reuse_lo_p (operands[4], operands[3], insn, | |
1276 | !rtx_equal_p (operands[1], operands[3]) | |
1277 | && !rtx_equal_p (operands[2], operands[3]) | |
1278 | && (rtx_equal_p (operands[0], operands[3]) | |
1279 | || peep2_reg_dead_p (1, operands[3])))" | |
1280 | [(parallel | |
1281 | [(set (match_dup 4) | |
1282 | (plus:SI (mult:SI (match_dup 0) | |
1283 | (match_dup 2)) | |
1284 | (match_dup 4))) | |
1285 | (set (match_dup 0) | |
1286 | (plus:SI (mult:SI (match_dup 0) | |
1287 | (match_dup 2)) | |
1288 | (match_dup 4))) | |
1289 | (clobber (match_dup 5))])] | |
1290 | "operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]);") | |
1291 | ||
1292 | ;; This splitter implements maddsi3 as "mulr;add3". It only works if | |
1293 | ;; operands 0 and 3 are distinct, since operand 0 is clobbered before | |
1294 | ;; operand 3 is used. | |
1295 | (define_split | |
1296 | [(set (match_operand:SI 0 "register_operand" "") | |
1297 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") | |
1298 | (match_operand:SI 2 "register_operand" "")) | |
1299 | (match_operand:SI 3 "register_operand" ""))) | |
1300 | (clobber (match_scratch:SI 4 "")) | |
1301 | (clobber (match_scratch:SI 5 ""))] | |
1302 | "TARGET_OPT_MULT | |
1303 | && reload_completed | |
1304 | && !rtx_equal_p (operands[0], operands[3])" | |
1305 | [(parallel [(set (match_dup 0) | |
1306 | (mult:SI (match_dup 0) | |
1307 | (match_dup 2))) | |
1308 | (clobber (match_dup 4)) | |
1309 | (clobber (match_dup 5))]) | |
1310 | (set (match_dup 0) | |
1311 | (plus:SI (match_dup 0) | |
1312 | (match_dup 3)))] | |
1313 | "operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]);") | |
1314 | ||
1315 | ;; This is the fallback splitter for maddsi3. It moves operand 3 into | |
1316 | ;; $lo and then uses maddr. | |
1317 | (define_split | |
1318 | [(set (match_operand:SI 0 "register_operand" "") | |
1319 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") | |
1320 | (match_operand:SI 2 "register_operand" "")) | |
1321 | (match_operand:SI 3 "register_operand" ""))) | |
1322 | (clobber (match_scratch:SI 4 "")) | |
1323 | (clobber (match_scratch:SI 5 ""))] | |
1324 | "TARGET_OPT_MULT | |
1325 | && reload_completed" | |
1326 | [(parallel [(set (match_dup 4) | |
1327 | (plus:SI (mult:SI (match_dup 0) | |
1328 | (match_dup 2)) | |
1329 | (match_dup 4))) | |
1330 | (set (match_dup 0) | |
1331 | (plus:SI (mult:SI (match_dup 0) | |
1332 | (match_dup 2)) | |
1333 | (match_dup 4))) | |
1334 | (clobber (match_dup 5))])] | |
1335 | { | |
1336 | emit_move_insn (operands[4], operands[3]); | |
1337 | operands[2] = mep_mulr_source (0, operands[0], operands[1], operands[2]); | |
1338 | }) | |
1339 | ||
1340 | ;; Remove unnecessary stcs to $lo. This cleans up the moves generated | |
1341 | ;; by earlier calls to mep_reuse_lo_p. | |
1342 | (define_peephole2 | |
1343 | [(set (match_operand:SI 0 "mep_lo_operand" "") | |
1344 | (match_operand:SI 1 "register_operand" ""))] | |
1345 | "TARGET_OPT_MULT | |
1346 | && mep_reuse_lo_p (operands[0], operands[1], insn, | |
1347 | peep2_reg_dead_p (1, operands[1]))" | |
1348 | [(const_int 0)] | |
1349 | { | |
1350 | emit_note (NOTE_INSN_DELETED); | |
1351 | DONE; | |
1352 | }) | |
1353 | ||
1354 | (define_insn "maddsi3_lo" | |
1355 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1356 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") | |
1357 | (match_operand:SI 2 "register_operand" "r")) | |
1358 | (match_operand:SI 3 "mep_lo_operand" "0"))) | |
1359 | (clobber (match_scratch:SI 4 "=h"))] | |
1360 | "TARGET_OPT_MULT && reload_completed" | |
1361 | "madd\\t%1, %2" | |
1362 | [(set_attr "length" "4") | |
1363 | (set_attr "stall" "mul")]) | |
1364 | ||
1365 | (define_insn "maddsi3r" | |
1366 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1367 | (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "1") | |
1368 | (match_operand:SI 3 "register_operand" "r")) | |
1369 | (match_operand:SI 4 "register_operand" "0"))) | |
1370 | (set (match_operand:SI 1 "register_operand" "=r") | |
1371 | (plus:SI (mult:SI (match_dup 2) | |
1372 | (match_dup 3)) | |
1373 | (match_dup 4))) | |
1374 | (clobber (match_scratch:SI 5 "=h"))] | |
1375 | "TARGET_OPT_MULT && reload_completed" | |
1376 | "maddr\\t%2, %3" | |
1377 | [(set_attr "length" "4") | |
1378 | (set_attr "stall" "mulr")]) | |
1379 | ||
1380 | (define_insn "*shift_1_or_2_and_add" | |
1381 | [(set (match_operand:SI 0 "mep_r0_operand" "=z") | |
1382 | (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") | |
1383 | (match_operand:SI 2 "mep_slad_operand" "n")) | |
1384 | (match_operand:SI 3 "register_operand" "r")))] | |
1385 | "" | |
1386 | "sl%b2ad3\\t%0, %1, %3" | |
1387 | [(set_attr "length" "2") | |
1388 | (set_attr "stall" "int2")]) | |
1389 | ||
1390 | (define_insn "divmodsi4" | |
1391 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1392 | (div:SI (match_operand:SI 1 "register_operand" "r") | |
1393 | (match_operand:SI 2 "register_operand" "r"))) | |
1394 | (set (match_operand:SI 3 "mep_hi_operand" "=h") | |
1395 | (mod:SI (match_dup 1) | |
1396 | (match_dup 2)))] | |
1397 | "TARGET_OPT_DIV" | |
1398 | "div\\t%1, %2" | |
1399 | [(set_attr "length" "2") | |
1400 | (set_attr "stall" "div") | |
1401 | (set_attr "may_trap" "yes")]) | |
1402 | ||
1403 | (define_insn "udivmodsi4" | |
1404 | [(set (match_operand:SI 0 "mep_lo_operand" "=l") | |
1405 | (udiv:SI (match_operand:SI 1 "register_operand" "r") | |
1406 | (match_operand:SI 2 "register_operand" "r"))) | |
1407 | (set (match_operand:SI 3 "mep_hi_operand" "=h") | |
1408 | (umod:SI (match_dup 1) | |
1409 | (match_dup 2)))] | |
1410 | "TARGET_OPT_DIV" | |
1411 | "divu\\t%1, %2" | |
1412 | [(set_attr "length" "2") | |
1413 | (set_attr "stall" "div") | |
1414 | (set_attr "may_trap" "yes")]) | |
1415 | ||
1416 | (define_insn "negsi2" | |
1417 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1418 | (neg:SI (match_operand:SI 1 "register_operand" "r")))] | |
1419 | "" | |
1420 | "neg\\t%0, %1" | |
1421 | [(set_attr "length" "2")]) | |
1422 | ||
1423 | ;; We have "absolute difference between two regs" which isn't quite | |
1424 | ;; what gcc is expecting. | |
1425 | (define_expand "abssi2" | |
1426 | [(set (match_dup 2) (const_int 0)) | |
1427 | (set (match_operand:SI 0 "register_operand" "") | |
1428 | (abs:SI (minus:SI (match_operand:SI 1 "register_operand" "") | |
1429 | (match_dup 2)) | |
1430 | ))] | |
1431 | "TARGET_OPT_ABSDIFF" | |
1432 | "operands[2] = gen_reg_rtx (SImode);") | |
1433 | ||
1434 | (define_insn "*absdiff" | |
1435 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1436 | (abs:SI (minus:SI (match_operand:SI 1 "register_operand" "0") | |
1437 | (match_operand:SI 2 "register_operand" "r"))))] | |
1438 | "TARGET_OPT_ABSDIFF" | |
1439 | "abs\\t%0, %2" | |
1440 | [(set_attr "length" "4")]) | |
1441 | ||
1442 | (define_split | |
1443 | [(set (match_operand:SI 0 "register_operand" "") | |
1444 | (abs:SI (plus:SI (match_operand:SI 1 "register_operand" "") | |
1445 | (match_operand:SI 2 "immediate_operand" "")))) | |
1446 | (clobber (match_operand:SI 3 "register_operand" ""))] | |
1447 | "!reload_completed" | |
1448 | [(set (match_dup 3) | |
1449 | (match_dup 4)) | |
1450 | (set (match_operand:SI 0 "register_operand" "") | |
1451 | (abs:SI (minus:SI (match_operand:SI 1 "register_operand" "") | |
1452 | (match_dup 3))))] | |
1453 | "operands[4] = GEN_INT (-INTVAL (operands[2]));") | |
1454 | ||
1455 | (define_insn "sminsi3" | |
1456 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1457 | (smin:SI (match_operand:SI 1 "register_operand" "0") | |
1458 | (match_operand:SI 2 "nonmemory_operand" "r")))] | |
1459 | "TARGET_OPT_MINMAX" | |
1460 | "min\\t%0, %2" | |
1461 | [(set_attr "length" "4")]) | |
1462 | ||
1463 | (define_insn "smaxsi3" | |
1464 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1465 | (smax:SI (match_operand:SI 1 "register_operand" "0") | |
1466 | (match_operand:SI 2 "nonmemory_operand" "r")))] | |
1467 | "TARGET_OPT_MINMAX" | |
1468 | "max\\t%0, %2" | |
1469 | [(set_attr "length" "4")]) | |
1470 | ||
1471 | (define_insn "uminsi3" | |
1472 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1473 | (umin:SI (match_operand:SI 1 "register_operand" "0") | |
1474 | (match_operand:SI 2 "nonmemory_operand" "r")))] | |
1475 | "TARGET_OPT_MINMAX" | |
1476 | "minu\\t%0, %2" | |
1477 | [(set_attr "length" "4")]) | |
1478 | ||
1479 | (define_insn "umaxsi3" | |
1480 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1481 | (umax:SI (match_operand:SI 1 "register_operand" "0") | |
1482 | (match_operand:SI 2 "nonmemory_operand" "r")))] | |
1483 | "TARGET_OPT_MINMAX" | |
1484 | "maxu\\t%0, %2" | |
1485 | [(set_attr "length" "4")]) | |
1486 | ||
1487 | ;; Average: a = (b+c+1)>>1 | |
1488 | (define_insn "*averagesi3" | |
1489 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1490 | (ashiftrt:SI (plus:SI (plus:SI | |
1491 | (match_operand:SI 1 "register_operand" "0") | |
1492 | (match_operand:SI 2 "register_operand" "r")) | |
1493 | (const_int 1)) | |
1494 | (const_int 1)))] | |
1495 | "TARGET_OPT_AVERAGE" | |
1496 | "ave\\t%0, %2" | |
1497 | [(set_attr "length" "4")]) | |
1498 | ||
1499 | ;; clip support | |
1500 | ||
1501 | (define_insn "clip_maxmin" | |
1502 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1503 | (smax:SI (smin:SI (match_operand:SI 1 "register_operand" "0") | |
1504 | (match_operand:SI 2 "immediate_operand" "n")) | |
1505 | (match_operand:SI 3 "immediate_operand" "n")))] | |
1506 | "mep_allow_clip (operands[2], operands[3], 1)" | |
1507 | "clip\\t%0, %B2" | |
1508 | [(set_attr "length" "4")]) | |
1509 | ||
1510 | (define_insn "clip_minmax" | |
1511 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1512 | (smin:SI (smax:SI (match_operand:SI 1 "register_operand" "0") | |
1513 | (match_operand:SI 2 "immediate_operand" "n")) | |
1514 | (match_operand:SI 3 "immediate_operand" "n")))] | |
1515 | "mep_allow_clip (operands[3], operands[2], 1)" | |
1516 | "clip\\t%0, %B3" | |
1517 | [(set_attr "length" "4")]) | |
1518 | ||
1519 | (define_insn "clipu_maxmin" | |
1520 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1521 | (smax:SI (smin:SI (match_operand:SI 1 "register_operand" "0") | |
1522 | (match_operand:SI 2 "immediate_operand" "n")) | |
1523 | (match_operand:SI 3 "immediate_operand" "n")))] | |
1524 | "mep_allow_clip (operands[2], operands[3], 0)" | |
1525 | "clipu\\t%0, %U2" | |
1526 | [(set_attr "length" "4")]) | |
1527 | ||
1528 | (define_insn "clipu_minmax" | |
1529 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1530 | (smin:SI (smax:SI (match_operand:SI 1 "register_operand" "0") | |
1531 | (match_operand:SI 2 "immediate_operand" "n")) | |
1532 | (match_operand:SI 3 "immediate_operand" "n")))] | |
1533 | "mep_allow_clip (operands[3], operands[2], 0)" | |
1534 | "clipu\\t%0, %U3" | |
1535 | [(set_attr "length" "4")]) | |
1536 | \f | |
1537 | ;; :::::::::::::::::::: | |
1538 | ;; :: | |
1539 | ;; :: 32 bit Integer Shifts and Rotates | |
1540 | ;; :: | |
1541 | ;; :::::::::::::::::::: | |
1542 | ||
1543 | (define_insn "ashlsi3" | |
1544 | [(set (match_operand:SI 0 "register_operand" "=r,z") | |
1545 | (ashift:SI (match_operand:SI 1 "register_operand" "0,r") | |
1546 | (match_operand:SI 2 "nonmemory_operand" "rM,M")))] | |
1547 | "" | |
1548 | "@ | |
1549 | sll\\t%0, %2 | |
1550 | sll3\\t%0, %1, %2" | |
1551 | [(set_attr "length" "2,2") | |
1552 | (set_attr "shiftop" "operand2")]) | |
1553 | ||
1554 | (define_insn "ashrsi3" | |
1555 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1556 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") | |
1557 | (match_operand:SI 2 "nonmemory_operand" "rM")))] | |
1558 | "" | |
1559 | "sra\\t%0, %2" | |
1560 | [(set_attr "length" "2") | |
1561 | (set_attr "shiftop" "operand2")]) | |
1562 | ||
1563 | (define_insn "lshrsi3" | |
1564 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1565 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") | |
1566 | (match_operand:SI 2 "nonmemory_operand" "rM")))] | |
1567 | "" | |
1568 | "srl\\t%0, %2" | |
1569 | [(set_attr "length" "2") | |
1570 | (set_attr "shiftop" "operand2")]) | |
1571 | \f | |
1572 | ;; :::::::::::::::::::: | |
1573 | ;; :: | |
1574 | ;; :: 32 Bit Integer Logical operations | |
1575 | ;; :: | |
1576 | ;; :::::::::::::::::::: | |
1577 | ||
1578 | (define_insn "andsi3" | |
1579 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1580 | (and:SI (match_operand:SI 1 "register_operand" "%0,r") | |
1581 | (match_operand:SI 2 "nonmemory_operand" "r,J")))] | |
1582 | "" | |
1583 | "@ | |
1584 | and\\t%0, %2 | |
1585 | and3\\t%0, %1, %J2" | |
1586 | [(set_attr "length" "2,4")]) | |
1587 | ||
1588 | (define_insn "iorsi3" | |
1589 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1590 | (ior:SI (match_operand:SI 1 "register_operand" "%0,r") | |
1591 | (match_operand:SI 2 "nonmemory_operand" "r,J")))] | |
1592 | "" | |
1593 | "@ | |
1594 | or\\t%0, %2 | |
1595 | or3\\t%0, %1, %J2" | |
1596 | [(set_attr "length" "2,4")]) | |
1597 | ||
1598 | (define_insn "xorsi3" | |
1599 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1600 | (xor:SI (match_operand:SI 1 "register_operand" "%0,r") | |
1601 | (match_operand:SI 2 "nonmemory_operand" "r,J")))] | |
1602 | "" | |
1603 | "@ | |
1604 | xor\\t%0, %2 | |
1605 | xor3\\t%0, %1, %J2" | |
1606 | [(set_attr "length" "2,4")]) | |
1607 | ||
1608 | (define_expand "one_cmplsi2" | |
1609 | [(set (match_operand:SI 0 "register_operand" "") | |
1610 | (not:SI (match_operand:SI 1 "register_operand" "")))] | |
1611 | "" | |
1612 | "operands[2] = operands[1]; | |
1613 | ") | |
1614 | ||
1615 | ;; No separate insn for this; use NOR | |
1616 | (define_insn "*one_cmplsi3_internal" | |
1617 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1618 | (not:SI (match_operand:SI 1 "register_operand" "0")))] | |
1619 | "" | |
1620 | "nor\\t%0, %0" | |
1621 | [(set_attr "length" "2")]) | |
1622 | \f | |
1623 | ;; :::::::::::::::::::: | |
1624 | ;; :: | |
1625 | ;; :: Bit Manipulation | |
1626 | ;; :: | |
1627 | ;; :::::::::::::::::::: | |
1628 | ||
1629 | (define_insn "*bitop_be" | |
1630 | [(set (match_operand:QI 0 "mep_Y_operand" "=Y") | |
1631 | (subreg:QI (match_operator:SI 3 "mep_bit_operator" | |
1632 | [(subreg:SI (match_operand:QI 1 "mep_Y_operand" "0") 0) | |
1633 | (match_operand 2 "immediate_operand" "n")]) | |
1634 | 3) | |
1635 | )] | |
1636 | "TARGET_BIG_ENDIAN && TARGET_OPT_BITOPS | |
1637 | && rtx_equal_p (operands[0], operands[1])" | |
1638 | "b%L3m\\t%0, %b2" | |
1639 | [(set_attr "length" "2")]) | |
1640 | ||
1641 | (define_insn "*bitop_le" | |
1642 | [(set (match_operand:QI 0 "mep_Y_operand" "=Y") | |
1643 | (subreg:QI (match_operator:SI 3 "mep_bit_operator" | |
1644 | [(subreg:SI (match_operand:QI 1 "mep_Y_operand" "0") 0) | |
1645 | (match_operand 2 "immediate_operand" "n")]) | |
1646 | 0) | |
1647 | )] | |
1648 | "!TARGET_BIG_ENDIAN && TARGET_OPT_BITOPS | |
1649 | && rtx_equal_p (operands[0], operands[1])" | |
1650 | "b%L3m\\t%0, %b2" | |
1651 | [(set_attr "length" "2")]) | |
1652 | ||
1653 | (define_insn "btstm" | |
1654 | [(set (match_operand:SI 0 "mep_r0_operand" "=z") | |
1655 | (and:SI (subreg:SI (match_operand:QI 1 "mep_Y_operand" "Y") 0) | |
1656 | (match_operand 2 "immediate_operand" "n")) | |
1657 | )] | |
1658 | "TARGET_OPT_BITOPS && mep_bit_position_p (operands[2], 1)" | |
1659 | "btstm\\t%0, %1, %b2" | |
1660 | [(set_attr "length" "2")]) | |
1661 | ||
1662 | (define_insn "tas" | |
1663 | [(parallel [(set (match_operand:SI 0 "mep_r0_operand" "=z") | |
1664 | (zero_extend:SI (match_operand:QI 1 "mep_Y_operand" "+Y"))) | |
1665 | (set (match_dup 1) | |
1666 | (const_int 1)) | |
1667 | ] | |
1668 | )] | |
1669 | "TARGET_OPT_BITOPS" | |
1670 | "tas\\t%0, %1" | |
1671 | [(set_attr "length" "2")]) | |
1672 | ||
1673 | (define_peephole2 | |
1674 | [(set (match_operand:SI 0 "mep_r0_operand" "") | |
1675 | (zero_extend:SI (match_operand:QI 1 "mep_Y_operand" ""))) | |
1676 | (set (match_operand:QI 2 "register_operand" "") | |
1677 | (const_int 1)) | |
1678 | (set (match_dup 1) | |
1679 | (match_dup 2)) | |
1680 | ] | |
1681 | "TARGET_OPT_BITOPS" | |
1682 | [(parallel [(set (match_dup 0) | |
1683 | (zero_extend:SI (match_dup 1))) | |
1684 | (set (match_dup 1) | |
1685 | (const_int 1)) | |
1686 | ])] | |
1687 | "") | |
1688 | ||
1689 | (define_peephole2 | |
1690 | [(set (match_operand:SI 0 "mep_r0_operand" "") | |
1691 | (sign_extend:SI (match_operand:QI 1 "mep_Y_operand" ""))) | |
1692 | (set (match_operand:QI 2 "register_operand" "") | |
1693 | (const_int 1)) | |
1694 | (set (match_dup 1) | |
1695 | (match_dup 2)) | |
1696 | ] | |
1697 | "TARGET_OPT_BITOPS" | |
1698 | [(parallel [(set (match_dup 0) | |
1699 | (zero_extend:SI (match_dup 1))) | |
1700 | (set (match_dup 1) | |
1701 | (const_int 1)) | |
1702 | ]) | |
1703 | (set (match_dup 0) | |
1704 | (sign_extend:SI (match_dup 3)))] | |
1705 | "operands[3] = gen_lowpart (QImode, operands[0]);") | |
1706 | ||
1707 | \f | |
1708 | ;; :::::::::::::::::::: | |
1709 | ;; :: | |
1710 | ;; :: Conditional branches and stores | |
1711 | ;; :: | |
1712 | ;; :::::::::::::::::::: | |
1713 | ||
1714 | (define_expand "cbranchsi4" | |
1715 | [(set (pc) | |
1716 | (if_then_else (match_operator 0 "ordered_comparison_operator" | |
1717 | [(match_operand:SI 1 "register_operand" "") | |
1718 | (match_operand:SI 2 "nonmemory_operand" "")]) | |
1719 | (label_ref (match_operand 3 "" "")) | |
1720 | (pc)))] | |
1721 | "" | |
1722 | "emit_jump_insn (gen_branch_true (operands[3], | |
1723 | mep_expand_cbranch (operands))); | |
1724 | DONE;") | |
1725 | ||
1726 | (define_expand "branch_true" | |
1727 | [(set (pc) | |
1728 | (if_then_else (match_operand 1 "" "") | |
1729 | (label_ref (match_operand 0 "" "")) | |
1730 | (pc)))] | |
1731 | "" | |
1732 | "") | |
1733 | ||
1734 | (define_expand "cstoresi4" | |
1735 | [(set (match_operand:SI 0 "register_operand" "") | |
1736 | (match_operator:SI 1 "ordered_comparison_operator" | |
1737 | [(match_operand:SI 2 "register_operand" "") | |
1738 | (match_operand:SI 3 "nonmemory_operand" "")]))] | |
1739 | "" | |
1740 | "if (mep_expand_setcc (operands)) DONE; else FAIL;") | |
1741 | ||
1742 | ;; ------------------------------------------------------------ | |
1743 | ||
1744 | (define_insn "*slt" | |
1745 | [(set (match_operand:SI 0 "register_operand" "=z,z,r") | |
1746 | (lt:SI (match_operand:SI 1 "register_operand" "r,r,r") | |
1747 | (match_operand:SI 2 "nonmemory_operand" "r,M,I")))] | |
1748 | "" | |
1749 | "slt3\\t%0, %1, %2" | |
1750 | [(set_attr "length" "2,2,4")]) | |
1751 | ||
1752 | (define_insn "*sltu" | |
1753 | [(set (match_operand:SI 0 "register_operand" "=z,z,r") | |
1754 | (ltu:SI (match_operand:SI 1 "register_operand" "r,r,r") | |
1755 | (match_operand:SI 2 "nonmemory_operand" "r,M,J")))] | |
1756 | "" | |
1757 | "sltu3\\t%0, %1, %2" | |
1758 | [(set_attr "length" "2,2,4")]) | |
1759 | ||
1760 | (define_insn "*bcpeq_true" | |
1761 | [(set (pc) | |
1762 | (if_then_else (eq:SI (reg:SI CBCR_REGNO) | |
1763 | (const_int 0)) | |
1764 | (label_ref (match_operand 0 "" "")) | |
1765 | (pc)))] | |
1766 | "" | |
1767 | "bcpeq\t0, %l0" | |
1768 | [(set_attr "length" "4")]) | |
1769 | ||
1770 | (define_insn "*bcpeq_false" | |
1771 | [(set (pc) | |
1772 | (if_then_else (eq:SI (reg:SI CBCR_REGNO) | |
1773 | (const_int 0)) | |
1774 | (pc) | |
1775 | (label_ref (match_operand 0 "" ""))))] | |
1776 | "" | |
1777 | "bcpne\t0, %l0" | |
1778 | [(set_attr "length" "4")]) | |
1779 | ||
1780 | (define_insn "*bcpne_true" | |
1781 | [(set (pc) | |
1782 | (if_then_else (ne:SI (reg:SI CBCR_REGNO) | |
1783 | (const_int 0)) | |
1784 | (label_ref (match_operand 0 "" "")) | |
1785 | (pc)))] | |
1786 | "" | |
1787 | "bcpne\t0, %l0" | |
1788 | [(set_attr "length" "4")]) | |
1789 | ||
1790 | (define_insn "*bcpne_false" | |
1791 | [(set (pc) | |
1792 | (if_then_else (ne:SI (reg:SI CBCR_REGNO) | |
1793 | (const_int 0)) | |
1794 | (pc) | |
1795 | (label_ref (match_operand 0 "" ""))))] | |
1796 | "" | |
1797 | "bcpeq\t0, %l0" | |
1798 | [(set_attr "length" "4")]) | |
1799 | ||
1800 | ;; ??? The lengths here aren't correct, since no attempt it made to | |
1801 | ;; find "beqz" in the 256-byte range. However, this should not affect | |
1802 | ;; bundling, since we never run core branches in parallel. | |
1803 | ||
1804 | (define_insn "mep_beq_true" | |
1805 | [(set (pc) | |
1806 | (if_then_else (eq (match_operand:SI 0 "register_operand" "r") | |
1807 | (match_operand:SI 1 "mep_reg_or_imm4_operand" "rN")) | |
1808 | (label_ref (match_operand 2 "" "")) | |
1809 | (pc)))] | |
1810 | "" | |
1811 | "* return mep_emit_cbranch (operands, 0);" | |
1812 | [(set_attr "length" "4")] ) | |
1813 | ||
1814 | (define_insn "*beq_false" | |
1815 | [(set (pc) | |
1816 | (if_then_else (eq (match_operand:SI 0 "register_operand" "r") | |
1817 | (match_operand:SI 1 "mep_reg_or_imm4_operand" "rN")) | |
1818 | (pc) | |
1819 | (label_ref (match_operand 2 "" ""))))] | |
1820 | "" | |
1821 | "* return mep_emit_cbranch (operands, 1);" | |
1822 | [(set_attr "length" "4")]) | |
1823 | ||
1824 | (define_insn "mep_bne_true" | |
1825 | [(set (pc) | |
1826 | (if_then_else (ne (match_operand:SI 0 "register_operand" "r") | |
1827 | (match_operand:SI 1 "mep_reg_or_imm4_operand" "rN")) | |
1828 | (label_ref (match_operand 2 "" "")) | |
1829 | (pc)))] | |
1830 | "" | |
1831 | "* return mep_emit_cbranch (operands, 1); " | |
1832 | [(set_attr "length" "4")]) | |
1833 | ||
1834 | (define_insn "*bne_false" | |
1835 | [(set (pc) | |
1836 | (if_then_else (ne (match_operand:SI 0 "register_operand" "r") | |
1837 | (match_operand:SI 1 "mep_reg_or_imm4_operand" "rN")) | |
1838 | (pc) | |
1839 | (label_ref (match_operand 2 "" ""))))] | |
1840 | "" | |
1841 | "* return mep_emit_cbranch (operands, 0); " | |
1842 | [(set_attr "length" "4")]) | |
1843 | ||
1844 | (define_insn "mep_blti" | |
1845 | [(set (pc) | |
1846 | (if_then_else (lt (match_operand:SI 0 "register_operand" "r") | |
1847 | (match_operand:SI 1 "mep_imm4_operand" "N")) | |
1848 | (label_ref (match_operand 2 "" "")) | |
1849 | (pc)))] | |
1850 | "" | |
1851 | "blti\\t%0, %1, %l2" | |
1852 | [(set_attr "length" "4")]) | |
1853 | ||
1854 | (define_insn "*bgei" | |
1855 | [(set (pc) | |
1856 | (if_then_else (ge (match_operand:SI 0 "register_operand" "r") | |
1857 | (match_operand:SI 1 "mep_imm4_operand" "N")) | |
1858 | (label_ref (match_operand 2 "" "")) | |
1859 | (pc)))] | |
1860 | "" | |
1861 | "bgei\\t%0, %1, %l2" | |
1862 | [(set_attr "length" "4")]) | |
1863 | \f | |
1864 | ;; :::::::::::::::::::: | |
1865 | ;; :: | |
1866 | ;; :: Call and branch instructions | |
1867 | ;; :: | |
1868 | ;; :::::::::::::::::::: | |
1869 | ||
1870 | (define_expand "call" | |
1871 | [(parallel [(call (match_operand:QI 0 "" "") | |
1872 | (match_operand:SI 1 "" "")) | |
1873 | (use (match_operand:SI 2 "" "")) | |
1874 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1875 | ])] | |
1876 | "" | |
1877 | " | |
1878 | { | |
1879 | mep_expand_call (operands, 0); | |
1880 | DONE; | |
1881 | }") | |
1882 | ||
1883 | (define_insn "call_internal" | |
1884 | [(call (mem (match_operand:SI 0 "mep_call_address_operand" "R,r")) | |
1885 | (match_operand:SI 1 "" "")) | |
1886 | (use (match_operand:SI 2 "const_int_operand" "")) | |
1887 | (use (match_operand:SI 3 "mep_tp_operand" "b,b")) | |
1888 | (use (match_operand:SI 4 "mep_gp_operand" "v,v")) | |
1889 | (clobber (reg:SI LP_REGNO)) | |
1890 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1891 | ] | |
1892 | "" | |
1893 | { | |
1894 | static char const pattern[2][2][8] = | |
1895 | { | |
1896 | { "bsrv\t%0", "jsrv\t%0" }, | |
1897 | { "bsr\t%0", "jsr\t%0" } | |
1898 | }; | |
1899 | ||
1900 | return pattern[mep_vliw_mode_match (operands[2])][which_alternative]; | |
1901 | } | |
1902 | [(set_attr "length" "4,2")]) | |
1903 | ||
1904 | (define_expand "sibcall" | |
1905 | [(parallel [(call (match_operand:QI 0 "" "") | |
1906 | (match_operand:SI 1 "" "")) | |
1907 | (use (match_operand:SI 2 "" "")) | |
1908 | (use (reg:SI LP_REGNO)) | |
1909 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1910 | ])] | |
1911 | "" | |
1912 | "") | |
1913 | ||
1914 | (define_insn "*sibcall_internal" | |
1915 | [(call (mem (match_operand:SI 0 "mep_nearsym_operand" "s")) | |
1916 | (match_operand:SI 1 "" "")) | |
1917 | (use (match_operand:SI 2 "const_int_operand" "")) | |
1918 | (use (reg:SI LP_REGNO)) | |
1919 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1920 | ] | |
1921 | "SIBLING_CALL_P (insn)" | |
1922 | { | |
2053b71f | 1923 | if (mep_vliw_jmp_match (operands[2])) |
46222c18 | 1924 | return "jmp\t%0"; |
93608695 | 1925 | else if (mep_vliw_mode_match (operands[2])) |
1926 | return | |
91f16f16 | 1927 | "movu $0, %0\n\ |
1928 | jmp $0"; | |
46222c18 | 1929 | else |
1930 | return | |
1931 | "ldc $12, $lp\n\ | |
1932 | movh $11, %%hi(%0)\n\ | |
1933 | xor3 $12, $12, 1\n\ | |
1934 | add3 $11, $11, %%lo(%0+1)\n\ | |
1935 | stc $12, $lp\n\ | |
1936 | jmp $11"; | |
1937 | } | |
1938 | [(set_attr "length" "48") | |
1939 | (set_attr "slot" "multi")]) | |
1940 | ||
1941 | (define_expand "call_value" | |
1942 | [(parallel [(set (match_operand 0 "" "") | |
1943 | (call (match_operand:QI 1 "" "") | |
1944 | (match_operand:SI 2 "" ""))) | |
1945 | (use (match_operand:SI 3 "" "")) | |
1946 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1947 | ])] | |
1948 | "" | |
1949 | " | |
1950 | { | |
1951 | mep_expand_call (operands, 1); | |
1952 | DONE; | |
1953 | }") | |
1954 | ||
1955 | (define_insn "call_value_internal" | |
1956 | [(set (match_operand 0 "register_operand" "=rx,rx") | |
1957 | (call (mem:SI (match_operand:SI 1 "mep_call_address_operand" "R,r")) | |
1958 | (match_operand:SI 2 "" ""))) | |
1959 | (use (match_operand:SI 3 "const_int_operand" "")) | |
1960 | (use (match_operand:SI 4 "mep_tp_operand" "b,b")) | |
1961 | (use (match_operand:SI 5 "mep_gp_operand" "v,v")) | |
1962 | (clobber (reg:SI LP_REGNO)) | |
1963 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1964 | ] | |
1965 | "" | |
1966 | { | |
1967 | static char const pattern[2][2][8] = | |
1968 | { | |
1969 | { "bsrv\t%1", "jsrv\t%1" }, | |
1970 | { "bsr\t%1", "jsr\t%1" } | |
1971 | }; | |
1972 | ||
1973 | return pattern[mep_vliw_mode_match (operands[3])][which_alternative]; | |
1974 | } | |
1975 | [(set_attr "length" "4,2")]) | |
1976 | ||
1977 | (define_expand "sibcall_value" | |
1978 | [(parallel [(set (match_operand 0 "" "") | |
1979 | (call (match_operand:QI 1 "" "") | |
1980 | (match_operand:SI 2 "" ""))) | |
1981 | (use (match_operand:SI 3 "" "")) | |
1982 | (use (reg:SI LP_REGNO)) | |
1983 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1984 | ])] | |
1985 | "" | |
1986 | "") | |
1987 | ||
1988 | (define_insn "*sibcall_value_internal" | |
1989 | [(set (match_operand 0 "register_operand" "=rx") | |
1990 | (call (mem (match_operand:SI 1 "mep_nearsym_operand" "s")) | |
1991 | (match_operand:SI 2 "" ""))) | |
1992 | (use (match_operand:SI 3 "const_int_operand" "")) | |
1993 | (use (reg:SI LP_REGNO)) | |
1994 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
1995 | ] | |
1996 | "SIBLING_CALL_P (insn)" | |
1997 | { | |
2053b71f | 1998 | if (mep_vliw_jmp_match (operands[3])) |
46222c18 | 1999 | return "jmp\t%1"; |
93608695 | 2000 | else if (mep_vliw_mode_match (operands[3])) |
2001 | return | |
91f16f16 | 2002 | "movu $0, %1\n\ |
2003 | jmp $0"; | |
46222c18 | 2004 | else |
2005 | return | |
2006 | "ldc $12, $lp\n\ | |
2007 | movh $11, %%hi(%1)\n\ | |
2008 | xor3 $12, $12, 1\n\ | |
2009 | add3 $11, $11, %%lo(%1+1)\n\ | |
2010 | stc $12, $lp\n\ | |
2011 | jmp $11"; | |
2012 | } | |
2013 | [(set_attr "length" "48") | |
2014 | (set_attr "slot" "multi")]) | |
2015 | ||
2016 | (define_insn "return_internal" | |
2017 | [(return) | |
2018 | (use (match_operand:SI 0 "register_operand" ""))] | |
2019 | "" | |
2020 | "* return (REGNO (operands[0]) == LP_REGNO) ? \"ret\" : \"jmp\\t%0\";" | |
2021 | [(set_attr "length" "2") | |
2022 | (set_attr "stall" "ret")]) | |
2023 | ||
2024 | (define_insn "eh_return_internal" | |
2025 | [(return) | |
2026 | (use (reg:SI 10)) | |
2027 | (use (reg:SI 11)) | |
2028 | (use (reg:SI LP_REGNO)) | |
2029 | (clobber (reg:SI REGSAVE_CONTROL_TEMP)) | |
2030 | ] | |
2031 | "" | |
2032 | "ret" | |
2033 | [(set_attr "length" "2") | |
2034 | (set_attr "stall" "ret")]) | |
2035 | ||
2036 | ;; The assembler replaces short jumps with long jumps as needed. | |
2037 | (define_insn "jump" | |
2038 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
2039 | "" | |
2040 | "bra\\t%l0" | |
2041 | [(set_attr "length" "4")]) | |
2042 | ||
2043 | (define_insn "indirect_jump" | |
2044 | [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
2045 | "" | |
2046 | "jmp\\t%0" | |
2047 | [(set_attr "length" "2")]) | |
2048 | ||
2049 | (define_insn "tablejump" | |
2050 | [(set (pc) (match_operand:SI 0 "register_operand" "r")) | |
2051 | (use (label_ref (match_operand 1 "" "")))] | |
2052 | "" | |
2053 | "jmp\\t%0" | |
2054 | [(set_attr "length" "2")]) | |
2055 | ||
2056 | \f | |
2057 | ;; :::::::::::::::::::: | |
2058 | ;; :: | |
2059 | ;; :: Low Overhead Looping | |
2060 | ;; :: | |
2061 | ;; :::::::::::::::::::: | |
2062 | ||
2063 | ;; This insn is volatile because we'd like it to stay in its original | |
2064 | ;; position, just before the loop header. If it stays there, we might | |
2065 | ;; be able to convert it into a "repeat" insn. | |
2066 | (define_insn "doloop_begin_internal" | |
2067 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2068 | (unspec_volatile:SI | |
2069 | [(match_operand:SI 1 "register_operand" "0") | |
2070 | (match_operand 2 "const_int_operand" "")] UNS_REPEAT_BEG))] | |
2071 | "" | |
2072 | { gcc_unreachable (); } | |
2073 | [(set_attr "length" "4")]) | |
2074 | ||
2075 | (define_expand "doloop_begin" | |
2076 | [(use (match_operand 0 "register_operand" "")) | |
5f35dd0e | 2077 | (use (match_operand 1 "" ""))] |
46222c18 | 2078 | "!profile_arc_flag && TARGET_OPT_REPEAT" |
5f35dd0e | 2079 | "mep_emit_doloop (operands, 0); |
46222c18 | 2080 | DONE; |
2081 | ") | |
2082 | ||
2083 | (define_insn "doloop_end_internal" | |
2084 | [(set (pc) | |
2085 | (if_then_else (ne (match_operand:SI 0 "nonimmediate_operand" "+r,cxy,*m") | |
2086 | (const_int 0)) | |
2087 | (label_ref (match_operand 1 "" "")) | |
2088 | (pc))) | |
2089 | (set (match_dup 0) | |
2090 | (plus:SI (match_dup 0) | |
2091 | (const_int -1))) | |
2092 | (unspec [(match_operand 2 "const_int_operand" "")] UNS_REPEAT_END) | |
2093 | (clobber (match_scratch:SI 3 "=X,&r,&r"))] | |
2094 | "" | |
2095 | { gcc_unreachable (); } | |
2096 | ;; Worst case length: | |
2097 | ;; | |
2098 | ;; lw <op3>,<op0> 4 | |
2099 | ;; add <op3>,-1 2 | |
2100 | ;; sw <op3>,<op0> 4 | |
2101 | ;; jmp <op1> 4 | |
2102 | ;; 1f: | |
2103 | [(set_attr "length" "14") | |
2104 | (set_attr "slot" "multi")]) | |
2105 | ||
2106 | (define_expand "doloop_end" | |
2107 | [(use (match_operand 0 "nonimmediate_operand" "")) | |
5f35dd0e | 2108 | (use (label_ref (match_operand 1 "" "")))] |
46222c18 | 2109 | "!profile_arc_flag && TARGET_OPT_REPEAT" |
5f35dd0e | 2110 | "if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) != SImode) |
46222c18 | 2111 | FAIL; |
2112 | mep_emit_doloop (operands, 1); | |
2113 | DONE; | |
2114 | ") | |
2115 | ||
2116 | (define_insn "repeat" | |
2117 | [(set (reg:SI RPC_REGNO) | |
2118 | (unspec:SI [(match_operand:SI 0 "mep_r0_15_operand" "r") | |
2119 | (match_operand:SI 1 "" "")] | |
2120 | UNS_REPEAT_BEG))] | |
2121 | "" | |
2122 | "repeat\\t%0,%l1" | |
2123 | [(set_attr "length" "4")]) | |
2124 | ||
2125 | (define_insn "repeat_end" | |
2126 | [(unspec [(const_int 0)] UNS_REPEAT_END)] | |
2127 | "" | |
2128 | "# repeat end" | |
2129 | [(set_attr "length" "0")]) | |
2130 | ||
2131 | (define_insn "erepeat" | |
2132 | [(unspec [(match_operand 0 "" "")] UNS_EREPEAT_BEG)] | |
2133 | "" | |
2134 | "erepeat\\t%l0" | |
2135 | [(set_attr "length" "4")]) | |
2136 | ||
2137 | (define_insn "erepeat_end" | |
2138 | [(unspec [(const_int 0)] UNS_EREPEAT_END)] | |
2139 | "" | |
2140 | "# erepeat end" | |
2141 | [(set_attr "length" "0") | |
2142 | (set_attr "slot" "multi")]) | |
2143 | ||
2144 | \f | |
2145 | ;; :::::::::::::::::::: | |
2146 | ;; :: | |
2147 | ;; :: Prologue and Epilogue instructions | |
2148 | ;; :: | |
2149 | ;; :::::::::::::::::::: | |
2150 | ||
2151 | (define_expand "prologue" | |
2152 | [(const_int 1)] | |
2153 | "" | |
2154 | " | |
2155 | { | |
2156 | mep_expand_prologue (); | |
2157 | DONE; | |
2158 | }") | |
2159 | ||
2160 | (define_expand "epilogue" | |
2161 | [(return)] | |
2162 | "" | |
2163 | " | |
2164 | { | |
2165 | mep_expand_epilogue (); | |
2166 | DONE; | |
2167 | }") | |
2168 | ||
2169 | (define_expand "eh_return" | |
2170 | [(use (match_operand:SI 0 "register_operand" "r"))] | |
2171 | "" | |
2172 | " | |
2173 | { | |
2174 | mep_expand_eh_return (operands); | |
2175 | DONE; | |
2176 | }") | |
2177 | ||
2178 | (define_insn_and_split "eh_epilogue" | |
2179 | [(unspec [(match_operand:SI 0 "register_operand" "r")] UNS_EH_EPILOGUE) | |
2180 | (use (reg:SI LP_REGNO))] | |
2181 | "" | |
2182 | "#" | |
f4eeff0e | 2183 | "epilogue_completed" |
46222c18 | 2184 | [(const_int 1)] |
2185 | "mep_emit_eh_epilogue (operands); DONE;" | |
2186 | [(set_attr "slot" "multi")]) | |
2187 | ||
2188 | (define_expand "sibcall_epilogue" | |
2189 | [(const_int 0)] | |
2190 | "" | |
2191 | " | |
2192 | { | |
2193 | mep_expand_sibcall_epilogue (); | |
2194 | DONE; | |
2195 | }") | |
2196 | ||
2197 | (define_insn "mep_bb_trace_ret" | |
2198 | [(unspec_volatile [(const_int 0)] UNS_BB_TRACE_RET)] | |
2199 | "" | |
2200 | "* return mep_emit_bb_trace_ret ();" | |
2201 | [(set_attr "slot" "multi")]) | |
2202 | ||
2203 | (define_insn "mep_disable_int" | |
2204 | [(unspec_volatile [(const_int 0)] UNS_DISABLE_INT)] | |
2205 | "" | |
2206 | "di" | |
2207 | [(set_attr "length" "2")]) | |
2208 | ||
2209 | (define_insn "mep_enable_int" | |
2210 | [(unspec_volatile [(const_int 0)] UNS_ENABLE_INT)] | |
2211 | "" | |
2212 | "ei" | |
2213 | [(set_attr "length" "2")]) | |
2214 | ||
2215 | (define_insn "mep_reti" | |
2216 | [(return) | |
2217 | (unspec_volatile [(const_int 0)] UNS_RETI)] | |
2218 | "" | |
2219 | "reti" | |
2220 | [(set_attr "length" "2")]) | |
2221 | \f | |
2222 | ;; :::::::::::::::::::: | |
2223 | ;; :: | |
2224 | ;; :: Miscellaneous instructions | |
2225 | ;; :: | |
2226 | ;; :::::::::::::::::::: | |
2227 | ||
2228 | (define_insn "nop" | |
2229 | [(const_int 0)] | |
2230 | "" | |
2231 | "nop" | |
2232 | [(set_attr "length" "2")]) | |
2233 | ||
2234 | (define_insn "nop32" | |
2235 | [(const_int 1)] | |
2236 | "" | |
2237 | "or3\\t$0, $0, 0" | |
2238 | [(set_attr "length" "4")]) | |
2239 | ||
2240 | (define_insn "blockage" | |
2241 | [(unspec_volatile [(const_int 0)] UNS_BLOCKAGE)] | |
2242 | "" | |
2243 | "" | |
2244 | [(set_attr "length" "0") | |
2245 | (set_attr "slot" "multi")]) | |
2246 | ||
2247 | ||
2248 | (define_insn "djmark" | |
2249 | [(unspec_volatile [(const_int 0)] 999)] | |
2250 | "" | |
2251 | "# dj" | |
2252 | [(set_attr "length" "0") | |
2253 | (set_attr "slot" "multi")]) | |
2254 |