Mercurial > hg > CbC > CbC_gcc
annotate gcc/config/mmix/mmix.md @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
rev | line source |
---|---|
0 | 1 ;; GCC machine description for MMIX |
131 | 2 ;; Copyright (C) 2000-2018 Free Software Foundation, Inc. |
0 | 3 ;; Contributed by Hans-Peter Nilsson (hp@bitrange.com) |
4 | |
5 ;; This file is part of GCC. | |
6 | |
7 ;; GCC is free software; you can redistribute it and/or modify | |
8 ;; it 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, | |
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 ;; GNU General Public 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 ;; The original PO technology requires these to be ordered by speed, | |
22 ;; so that assigner will pick the fastest. | |
23 | |
24 ;; See file "rtl.def" for documentation on define_insn, match_*, et al. | |
25 | |
26 ;; Uses of UNSPEC in this file: | |
27 ;; UNSPEC_VOLATILE: | |
28 ;; | |
29 ;; 0 sync_icache (sync icache before trampoline jump) | |
30 ;; 1 nonlocal_goto_receiver | |
31 ;; | |
32 | |
33 ;; The order of insns is as in Node: Standard Names, with smaller modes | |
34 ;; before bigger modes. | |
35 | |
36 (define_constants | |
37 [(MMIX_rJ_REGNUM 259) | |
38 (MMIX_rR_REGNUM 260) | |
39 (MMIX_fp_rO_OFFSET -24)] | |
40 ) | |
41 | |
42 ;; Operand and operator predicates. | |
43 | |
44 (include "predicates.md") | |
111 | 45 (include "constraints.md") |
0 | 46 |
47 ;; FIXME: Can we remove the reg-to-reg for smaller modes? Shouldn't they | |
48 ;; be synthesized ok? | |
49 (define_insn "movqi" | |
50 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r ,r,x ,r,r,m,??r") | |
51 (match_operand:QI 1 "general_operand" "r,LS,K,rI,x,m,r,n"))] | |
52 "" | |
53 "@ | |
54 SET %0,%1 | |
55 %s1 %0,%v1 | |
56 NEGU %0,0,%n1 | |
57 PUT %0,%1 | |
58 GET %0,%1 | |
59 LDB%U0 %0,%1 | |
60 STBU %1,%0 | |
61 %r0%I1") | |
62 | |
63 (define_insn "movhi" | |
64 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,x,r,r,m,??r") | |
65 (match_operand:HI 1 "general_operand" "r,LS,K,r,x,m,r,n"))] | |
66 "" | |
67 "@ | |
68 SET %0,%1 | |
69 %s1 %0,%v1 | |
70 NEGU %0,0,%n1 | |
71 PUT %0,%1 | |
72 GET %0,%1 | |
73 LDW%U0 %0,%1 | |
74 STWU %1,%0 | |
75 %r0%I1") | |
76 | |
77 ;; gcc.c-torture/compile/920428-2.c fails if there's no "n". | |
78 (define_insn "movsi" | |
79 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r") | |
80 (match_operand:SI 1 "general_operand" "r,LS,K,r,x,m,r,n"))] | |
81 "" | |
82 "@ | |
83 SET %0,%1 | |
84 %s1 %0,%v1 | |
85 NEGU %0,0,%n1 | |
86 PUT %0,%1 | |
87 GET %0,%1 | |
88 LDT%U0 %0,%1 | |
89 STTU %1,%0 | |
90 %r0%I1") | |
91 | |
92 ;; We assume all "s" are addresses. Does that hold? | |
93 (define_insn "movdi" | |
94 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r") | |
95 (match_operand:DI 1 "general_operand" "r,LS,K,r,x,I,m,r,R,s,n"))] | |
96 "" | |
97 "@ | |
98 SET %0,%1 | |
99 %s1 %0,%v1 | |
100 NEGU %0,0,%n1 | |
101 PUT %0,%1 | |
102 GET %0,%1 | |
103 STCO %1,%0 | |
104 LDO %0,%1 | |
105 STOU %1,%0 | |
106 GETA %0,%1 | |
107 LDA %0,%1 | |
108 %r0%I1") | |
109 | |
110 ;; Note that we move around the float as a collection of bits; no | |
111 ;; conversion to double. | |
112 (define_insn "movsf" | |
113 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r") | |
114 (match_operand:SF 1 "general_operand" "r,G,r,x,m,r,F"))] | |
115 "" | |
116 "@ | |
117 SET %0,%1 | |
118 SETL %0,0 | |
119 PUT %0,%1 | |
120 GET %0,%1 | |
121 LDT %0,%1 | |
122 STTU %1,%0 | |
123 %r0%I1") | |
124 | |
125 (define_insn "movdf" | |
126 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r") | |
127 (match_operand:DF 1 "general_operand" "r,G,r,x,m,r,F"))] | |
128 "" | |
129 "@ | |
130 SET %0,%1 | |
131 SETL %0,0 | |
132 PUT %0,%1 | |
133 GET %0,%1 | |
134 LDO %0,%1 | |
135 STOU %1,%0 | |
136 %r0%I1") | |
137 | |
138 ;; We need to be able to move around the values used as condition codes. | |
139 ;; First spotted as reported in | |
140 ;; <URL:http://gcc.gnu.org/ml/gcc-bugs/2003-03/msg00008.html> due to | |
141 ;; changes in loop optimization. The file machmode.def says they're of | |
142 ;; size 4 QI. Valid bit-patterns correspond to integers -1, 0 and 1, so | |
143 ;; we treat them as signed entities; see mmix-modes.def. The following | |
144 ;; expanders should cover all MODE_CC modes, and expand for this pattern. | |
145 (define_insn "*movcc_expanded" | |
146 [(set (match_operand 0 "nonimmediate_operand" "=r,x,r,r,m") | |
147 (match_operand 1 "nonimmediate_operand" "r,r,x,m,r"))] | |
148 "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_CC | |
149 && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_CC" | |
150 "@ | |
151 SET %0,%1 | |
152 PUT %0,%1 | |
153 GET %0,%1 | |
154 LDT %0,%1 | |
155 STT %1,%0") | |
156 | |
157 (define_expand "movcc" | |
158 [(set (match_operand:CC 0 "nonimmediate_operand" "") | |
159 (match_operand:CC 1 "nonimmediate_operand" ""))] | |
160 "" | |
161 "") | |
162 | |
163 (define_expand "movcc_uns" | |
164 [(set (match_operand:CC_UNS 0 "nonimmediate_operand" "") | |
165 (match_operand:CC_UNS 1 "nonimmediate_operand" ""))] | |
166 "" | |
167 "") | |
168 | |
169 (define_expand "movcc_fp" | |
170 [(set (match_operand:CC_FP 0 "nonimmediate_operand" "") | |
171 (match_operand:CC_FP 1 "nonimmediate_operand" ""))] | |
172 "" | |
173 "") | |
174 | |
175 (define_expand "movcc_fpeq" | |
176 [(set (match_operand:CC_FPEQ 0 "nonimmediate_operand" "") | |
177 (match_operand:CC_FPEQ 1 "nonimmediate_operand" ""))] | |
178 "" | |
179 "") | |
180 | |
181 (define_expand "movcc_fun" | |
182 [(set (match_operand:CC_FUN 0 "nonimmediate_operand" "") | |
183 (match_operand:CC_FUN 1 "nonimmediate_operand" ""))] | |
184 "" | |
185 "") | |
186 | |
187 (define_insn "adddi3" | |
188 [(set (match_operand:DI 0 "register_operand" "=r,r,r") | |
189 (plus:DI | |
190 (match_operand:DI 1 "register_operand" "%r,r,0") | |
191 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))] | |
192 "" | |
193 "@ | |
194 ADDU %0,%1,%2 | |
195 SUBU %0,%1,%n2 | |
196 %i2 %0,%v2") | |
197 | |
198 (define_insn "adddf3" | |
199 [(set (match_operand:DF 0 "register_operand" "=r") | |
200 (plus:DF (match_operand:DF 1 "register_operand" "%r") | |
201 (match_operand:DF 2 "register_operand" "r")))] | |
202 "" | |
203 "FADD %0,%1,%2") | |
204 | |
205 ;; Insn canonicalization *should* have removed the need for an integer | |
206 ;; in operand 2. | |
207 (define_insn "subdi3" | |
208 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
209 (minus:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "r,I") | |
210 (match_operand:DI 2 "register_operand" "r,r")))] | |
211 "" | |
212 "@ | |
213 SUBU %0,%1,%2 | |
214 NEGU %0,%1,%2") | |
215 | |
216 (define_insn "subdf3" | |
217 [(set (match_operand:DF 0 "register_operand" "=r") | |
218 (minus:DF (match_operand:DF 1 "register_operand" "r") | |
219 (match_operand:DF 2 "register_operand" "r")))] | |
220 "" | |
221 "FSUB %0,%1,%2") | |
222 | |
223 ;; FIXME: Should we define_expand and match 2, 4, 8 (etc) with shift (or | |
224 ;; %{something}2ADDU %0,%1,0)? Hopefully GCC should still handle it, so | |
225 ;; we don't have to taint the machine description. If results are bad | |
226 ;; enough, we may have to do it anyway. | |
227 (define_insn "muldi3" | |
228 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
229 (mult:DI (match_operand:DI 1 "register_operand" "%r,r") | |
230 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "O,rI"))) | |
231 (clobber (match_scratch:DI 3 "=X,z"))] | |
232 "" | |
233 "@ | |
234 %m2ADDU %0,%1,%1 | |
235 MULU %0,%1,%2") | |
236 | |
237 (define_insn "muldf3" | |
238 [(set (match_operand:DF 0 "register_operand" "=r") | |
239 (mult:DF (match_operand:DF 1 "register_operand" "r") | |
240 (match_operand:DF 2 "register_operand" "r")))] | |
241 "" | |
242 "FMUL %0,%1,%2") | |
243 | |
244 (define_insn "divdf3" | |
245 [(set (match_operand:DF 0 "register_operand" "=r") | |
246 (div:DF (match_operand:DF 1 "register_operand" "r") | |
247 (match_operand:DF 2 "register_operand" "r")))] | |
248 "" | |
249 "FDIV %0,%1,%2") | |
250 | |
251 ;; FIXME: Is "frem" doing the right operation for moddf3? | |
252 (define_insn "moddf3" | |
253 [(set (match_operand:DF 0 "register_operand" "=r") | |
254 (mod:DF (match_operand:DF 1 "register_operand" "r") | |
255 (match_operand:DF 2 "register_operand" "r")))] | |
256 "" | |
257 "FREM %0,%1,%2") | |
258 | |
259 ;; FIXME: Should we define_expand for smin, smax, umin, umax using a | |
260 ;; nifty conditional sequence? | |
261 | |
262 ;; FIXME: The cuter andn combinations don't get here, presumably because | |
263 ;; they ended up in the constant pool. Check: still? | |
264 (define_insn "anddi3" | |
265 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
266 (and:DI | |
267 (match_operand:DI 1 "register_operand" "%r,0") | |
268 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))] | |
269 "" | |
270 "@ | |
271 AND %0,%1,%2 | |
272 %A2 %0,%V2") | |
273 | |
274 (define_insn "iordi3" | |
275 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
276 (ior:DI (match_operand:DI 1 "register_operand" "%r,0") | |
111 | 277 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,LS")))] |
0 | 278 "" |
279 "@ | |
280 OR %0,%1,%2 | |
281 %o2 %0,%v2") | |
282 | |
283 (define_insn "xordi3" | |
284 [(set (match_operand:DI 0 "register_operand" "=r") | |
285 (xor:DI (match_operand:DI 1 "register_operand" "%r") | |
286 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] | |
287 "" | |
288 "XOR %0,%1,%2") | |
289 | |
290 ;; FIXME: When TImode works for other reasons (like cross-compiling from | |
291 ;; a 32-bit host), add back umulditi3 and umuldi3_highpart here. | |
292 | |
293 ;; FIXME: Check what's really reasonable for the mod part. | |
294 | |
295 ;; One day we might persuade GCC to expand divisions with constants the | |
296 ;; way MMIX does; giving the remainder the sign of the divisor. But even | |
297 ;; then, it might be good to have an option to divide the way "everybody | |
298 ;; else" does. Perhaps then, this option can be on by default. However, | |
299 ;; it's not likely to happen because major (C, C++, Fortran) language | |
300 ;; standards in effect at 2002-04-29 reportedly demand that the sign of | |
301 ;; the remainder must follow the sign of the dividend. | |
302 | |
303 (define_insn "divmoddi4" | |
304 [(set (match_operand:DI 0 "register_operand" "=r") | |
305 (div:DI (match_operand:DI 1 "register_operand" "r") | |
306 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))) | |
307 (set (match_operand:DI 3 "register_operand" "=y") | |
308 (mod:DI (match_dup 1) (match_dup 2)))] | |
309 ;; Do the library stuff later. | |
310 "TARGET_KNUTH_DIVISION" | |
311 "DIV %0,%1,%2") | |
312 | |
313 (define_insn "udivmoddi4" | |
314 [(set (match_operand:DI 0 "register_operand" "=r") | |
315 (udiv:DI (match_operand:DI 1 "register_operand" "r") | |
316 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))) | |
317 (set (match_operand:DI 3 "register_operand" "=y") | |
318 (umod:DI (match_dup 1) (match_dup 2)))] | |
319 "" | |
320 "DIVU %0,%1,%2") | |
321 | |
322 (define_expand "divdi3" | |
323 [(parallel | |
324 [(set (match_operand:DI 0 "register_operand" "=&r") | |
325 (div:DI (match_operand:DI 1 "register_operand" "r") | |
326 (match_operand:DI 2 "register_operand" "r"))) | |
327 (clobber (scratch:DI)) | |
328 (clobber (scratch:DI)) | |
329 (clobber (reg:DI MMIX_rR_REGNUM))])] | |
330 "! TARGET_KNUTH_DIVISION" | |
331 "") | |
332 | |
333 ;; The %2-is-%1-case is there just to make sure things don't fail. Could | |
334 ;; presumably happen with optimizations off; no evidence. | |
335 (define_insn "*divdi3_nonknuth" | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
336 [(set (match_operand:DI 0 "register_operand" "=&r,&r") |
0 | 337 (div:DI (match_operand:DI 1 "register_operand" "r,r") |
338 (match_operand:DI 2 "register_operand" "1,r"))) | |
339 (clobber (match_scratch:DI 3 "=1,1")) | |
340 (clobber (match_scratch:DI 4 "=2,2")) | |
341 (clobber (reg:DI MMIX_rR_REGNUM))] | |
342 "! TARGET_KNUTH_DIVISION" | |
343 "@ | |
344 SETL %0,1 | |
345 XOR $255,%1,%2\;NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU %0,0,%1\;CSN %1,%1,%0\;\ | |
346 DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1") | |
347 | |
348 (define_expand "moddi3" | |
349 [(parallel | |
350 [(set (match_operand:DI 0 "register_operand" "=&r") | |
351 (mod:DI (match_operand:DI 1 "register_operand" "r") | |
352 (match_operand:DI 2 "register_operand" "r"))) | |
353 (clobber (scratch:DI)) | |
354 (clobber (scratch:DI)) | |
355 (clobber (reg:DI MMIX_rR_REGNUM))])] | |
356 "! TARGET_KNUTH_DIVISION" | |
357 "") | |
358 | |
359 ;; The %2-is-%1-case is there just to make sure things don't fail. Could | |
360 ;; presumably happen with optimizations off; no evidence. | |
361 (define_insn "*moddi3_nonknuth" | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
362 [(set (match_operand:DI 0 "register_operand" "=&r,&r") |
0 | 363 (mod:DI (match_operand:DI 1 "register_operand" "r,r") |
364 (match_operand:DI 2 "register_operand" "1,r"))) | |
365 (clobber (match_scratch:DI 3 "=1,1")) | |
366 (clobber (match_scratch:DI 4 "=2,2")) | |
367 (clobber (reg:DI MMIX_rR_REGNUM))] | |
368 "! TARGET_KNUTH_DIVISION" | |
369 "@ | |
370 SETL %0,0 | |
371 NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU $255,0,%1\;CSN %1,%1,$255\;\ | |
372 DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") | |
373 | |
374 (define_insn "ashldi3" | |
375 [(set (match_operand:DI 0 "register_operand" "=r") | |
376 (ashift:DI | |
377 (match_operand:DI 1 "register_operand" "r") | |
378 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] | |
379 "" | |
380 "SLU %0,%1,%2") | |
381 | |
382 (define_insn "ashrdi3" | |
383 [(set (match_operand:DI 0 "register_operand" "=r") | |
384 (ashiftrt:DI | |
385 (match_operand:DI 1 "register_operand" "r") | |
386 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] | |
387 "" | |
388 "SR %0,%1,%2") | |
389 | |
390 (define_insn "lshrdi3" | |
391 [(set (match_operand:DI 0 "register_operand" "=r") | |
392 (lshiftrt:DI | |
393 (match_operand:DI 1 "register_operand" "r") | |
394 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] | |
395 "" | |
396 "SRU %0,%1,%2") | |
397 | |
398 (define_insn "negdi2" | |
399 [(set (match_operand:DI 0 "register_operand" "=r") | |
400 (neg:DI (match_operand:DI 1 "register_operand" "r")))] | |
401 "" | |
402 "NEGU %0,0,%1") | |
403 | |
404 (define_expand "negdf2" | |
405 [(parallel [(set (match_operand:DF 0 "register_operand" "=r") | |
406 (neg:DF (match_operand:DF 1 "register_operand" "r"))) | |
407 (use (match_dup 2))])] | |
408 "" | |
409 { | |
410 /* Emit bit-flipping sequence to be IEEE-safe wrt. -+0. */ | |
411 operands[2] = force_reg (DImode, GEN_INT ((HOST_WIDE_INT) 1 << 63)); | |
412 }) | |
413 | |
414 (define_insn "*expanded_negdf2" | |
415 [(set (match_operand:DF 0 "register_operand" "=r") | |
416 (neg:DF (match_operand:DF 1 "register_operand" "r"))) | |
417 (use (match_operand:DI 2 "register_operand" "r"))] | |
418 "" | |
419 "XOR %0,%1,%2") | |
420 | |
421 ;; FIXME: define_expand for absdi2? | |
422 | |
423 (define_insn "absdf2" | |
424 [(set (match_operand:DF 0 "register_operand" "=r") | |
425 (abs:DF (match_operand:DF 1 "register_operand" "0")))] | |
426 "" | |
427 "ANDNH %0,#8000") | |
428 | |
429 (define_insn "sqrtdf2" | |
430 [(set (match_operand:DF 0 "register_operand" "=r") | |
431 (sqrt:DF (match_operand:DF 1 "register_operand" "r")))] | |
432 "" | |
433 "FSQRT %0,%1") | |
434 | |
435 ;; FIXME: define_expand for ffssi2? (not ffsdi2 since int is SImode). | |
436 | |
437 (define_insn "one_cmpldi2" | |
438 [(set (match_operand:DI 0 "register_operand" "=r") | |
439 (not:DI (match_operand:DI 1 "register_operand" "r")))] | |
440 "" | |
441 "NOR %0,%1,0") | |
442 | |
443 ;; When the user-patterns expand, the resulting insns will match the | |
444 ;; patterns below. | |
445 | |
446 ;; We can fold the signed-compare where the register value is | |
447 ;; already equal to (compare:CCTYPE (reg) (const_int 0)). | |
448 ;; We can't do that at all for floating-point, due to NaN, +0.0 | |
449 ;; and -0.0, and we can only do it for the non/zero test of | |
450 ;; unsigned, so that has to be done another way. | |
451 ;; FIXME: Perhaps a peep2 changing CCcode to a new code, that | |
452 ;; gets folded here. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
453 (define_insn "*cmpdi_folded" |
0 | 454 [(set (match_operand:CC 0 "register_operand" "=r") |
455 (compare:CC | |
456 (match_operand:DI 1 "register_operand" "r") | |
457 (const_int 0)))] | |
458 ;; FIXME: Can we test equivalence any other way? | |
459 ;; FIXME: Can we fold any other way? | |
460 "REG_P (operands[0]) && REG_P (operands[1]) | |
461 && REGNO (operands[1]) == REGNO (operands[0])" | |
462 "%% folded: cmp %0,%1,0") | |
463 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
464 (define_insn "*cmps" |
0 | 465 [(set (match_operand:CC 0 "register_operand" "=r") |
466 (compare:CC | |
467 (match_operand:DI 1 "register_operand" "r") | |
468 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] | |
469 "" | |
470 "CMP %0,%1,%2") | |
471 | |
472 (define_insn "*cmpu" | |
473 [(set (match_operand:CC_UNS 0 "register_operand" "=r") | |
474 (compare:CC_UNS | |
475 (match_operand:DI 1 "register_operand" "r") | |
476 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] | |
477 "" | |
478 "CMPU %0,%1,%2") | |
479 | |
480 (define_insn "*fcmp" | |
481 [(set (match_operand:CC_FP 0 "register_operand" "=r") | |
482 (compare:CC_FP | |
483 (match_operand:DF 1 "register_operand" "r") | |
484 (match_operand:DF 2 "register_operand" "r")))] | |
485 "" | |
486 "FCMP%e0 %0,%1,%2") | |
487 | |
488 ;; FIXME: for -mieee, add fsub %0,%1,%1\;fsub %0,%2,%2 before to | |
489 ;; make signalling compliant. | |
490 (define_insn "*feql" | |
491 [(set (match_operand:CC_FPEQ 0 "register_operand" "=r") | |
492 (compare:CC_FPEQ | |
493 (match_operand:DF 1 "register_operand" "r") | |
494 (match_operand:DF 2 "register_operand" "r")))] | |
495 "" | |
496 "FEQL%e0 %0,%1,%2") | |
497 | |
498 (define_insn "*fun" | |
499 [(set (match_operand:CC_FUN 0 "register_operand" "=r") | |
500 (compare:CC_FUN | |
501 (match_operand:DF 1 "register_operand" "r") | |
502 (match_operand:DF 2 "register_operand" "r")))] | |
503 "" | |
504 "FUN%e0 %0,%1,%2") | |
505 | |
506 ;; In order to get correct rounding, we have to use SFLOT and SFLOTU for | |
507 ;; conversion. They do not convert to SFmode; they convert to DFmode, | |
508 ;; with rounding as of SFmode. They are not usable as is, but we pretend | |
509 ;; we have a single instruction but emit two. | |
510 | |
511 ;; Note that this will (somewhat unexpectedly) create an inexact | |
512 ;; exception if rounding is necessary - has to be masked off in crt0? | |
513 (define_expand "floatdisf2" | |
514 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm") | |
515 (float:SF | |
516 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))) | |
517 ;; Let's use a DI scratch, since SF don't generally get into | |
518 ;; registers. Dunno what's best; it's really a DF, but that | |
519 ;; doesn't logically follow from operands in the pattern. | |
520 (clobber (match_scratch:DI 2 "=&r"))])] | |
521 "" | |
522 " | |
523 { | |
524 if (GET_CODE (operands[0]) != MEM) | |
525 { | |
526 rtx stack_slot; | |
527 | |
528 /* FIXME: This stack-slot remains even at -O3. There must be a | |
529 better way. */ | |
530 stack_slot | |
531 = validize_mem (assign_stack_temp (SFmode, | |
111 | 532 GET_MODE_SIZE (SFmode))); |
0 | 533 emit_insn (gen_floatdisf2 (stack_slot, operands[1])); |
534 emit_move_insn (operands[0], stack_slot); | |
535 DONE; | |
536 } | |
537 }") | |
538 | |
539 (define_insn "*floatdisf2_real" | |
540 [(set (match_operand:SF 0 "memory_operand" "=m") | |
541 (float:SF | |
542 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))) | |
543 (clobber (match_scratch:DI 2 "=&r"))] | |
544 "" | |
545 "SFLOT %2,%1\;STSF %2,%0") | |
546 | |
547 (define_expand "floatunsdisf2" | |
548 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm") | |
549 (unsigned_float:SF | |
550 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))) | |
551 ;; Let's use a DI scratch, since SF don't generally get into | |
552 ;; registers. Dunno what's best; it's really a DF, but that | |
553 ;; doesn't logically follow from operands in the pattern. | |
554 (clobber (scratch:DI))])] | |
555 "" | |
556 " | |
557 { | |
558 if (GET_CODE (operands[0]) != MEM) | |
559 { | |
560 rtx stack_slot; | |
561 | |
562 /* FIXME: This stack-slot remains even at -O3. Must be a better | |
563 way. */ | |
564 stack_slot | |
565 = validize_mem (assign_stack_temp (SFmode, | |
111 | 566 GET_MODE_SIZE (SFmode))); |
0 | 567 emit_insn (gen_floatunsdisf2 (stack_slot, operands[1])); |
568 emit_move_insn (operands[0], stack_slot); | |
569 DONE; | |
570 } | |
571 }") | |
572 | |
573 (define_insn "*floatunsdisf2_real" | |
574 [(set (match_operand:SF 0 "memory_operand" "=m") | |
575 (unsigned_float:SF | |
576 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))) | |
577 (clobber (match_scratch:DI 2 "=&r"))] | |
578 "" | |
579 "SFLOTU %2,%1\;STSF %2,%0") | |
580 | |
581 ;; Note that this will (somewhat unexpectedly) create an inexact | |
582 ;; exception if rounding is necessary - has to be masked off in crt0? | |
583 (define_insn "floatdidf2" | |
584 [(set (match_operand:DF 0 "register_operand" "=r") | |
585 (float:DF | |
586 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))] | |
587 "" | |
588 "FLOT %0,%1") | |
589 | |
590 (define_insn "floatunsdidf2" | |
591 [(set (match_operand:DF 0 "register_operand" "=r") | |
592 (unsigned_float:DF | |
593 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))] | |
594 "" | |
595 "FLOTU %0,%1") | |
596 | |
597 (define_insn "ftruncdf2" | |
598 [(set (match_operand:DF 0 "register_operand" "=r") | |
599 (fix:DF (match_operand:DF 1 "register_operand" "r")))] | |
600 "" | |
601 ;; ROUND_OFF | |
602 "FINT %0,1,%1") | |
603 | |
604 ;; Note that this will (somewhat unexpectedly) create an inexact | |
605 ;; exception if rounding is necessary - has to be masked off in crt0? | |
606 (define_insn "fix_truncdfdi2" | |
607 [(set (match_operand:DI 0 "register_operand" "=r") | |
608 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "r"))))] | |
609 "" | |
610 ;; ROUND_OFF | |
611 "FIX %0,1,%1") | |
612 | |
613 (define_insn "fixuns_truncdfdi2" | |
614 [(set (match_operand:DI 0 "register_operand" "=r") | |
615 (unsigned_fix:DI | |
616 (fix:DF (match_operand:DF 1 "register_operand" "r"))))] | |
617 "" | |
618 ;; ROUND_OFF | |
619 "FIXU %0,1,%1") | |
620 | |
621 ;; It doesn't seem like it's possible to have memory_operand as a | |
622 ;; predicate here (testcase: libgcc2 floathisf). FIXME: Shouldn't it be | |
623 ;; possible to do that? Bug in GCC? Anyway, this used to be a simple | |
624 ;; pattern with a memory_operand predicate, but was split up with a | |
625 ;; define_expand with the old pattern as "anonymous". | |
111 | 626 ;; FIXME: Perhaps with TARGET_SECONDARY_MEMORY_NEEDED? |
0 | 627 (define_expand "truncdfsf2" |
111 | 628 [(set (match_operand:SF 0 "nonimmediate_operand") |
629 (float_truncate:SF (match_operand:DF 1 "register_operand")))] | |
0 | 630 "" |
631 " | |
632 { | |
633 if (GET_CODE (operands[0]) != MEM) | |
634 { | |
635 /* FIXME: There should be a way to say: 'put this in operands[0] | |
636 but *after* the expanded insn'. */ | |
637 rtx stack_slot; | |
638 | |
639 /* There is no sane destination but a register here, if it wasn't | |
640 already MEM. (It's too hard to get fatal_insn to work here.) */ | |
641 if (! REG_P (operands[0])) | |
642 internal_error (\"MMIX Internal: Bad truncdfsf2 expansion\"); | |
643 | |
644 /* FIXME: This stack-slot remains even at -O3. Must be a better | |
645 way. */ | |
646 stack_slot | |
647 = validize_mem (assign_stack_temp (SFmode, | |
111 | 648 GET_MODE_SIZE (SFmode))); |
0 | 649 emit_insn (gen_truncdfsf2 (stack_slot, operands[1])); |
650 emit_move_insn (operands[0], stack_slot); | |
651 DONE; | |
652 } | |
653 }") | |
654 | |
655 (define_insn "*truncdfsf2_real" | |
656 [(set (match_operand:SF 0 "memory_operand" "=m") | |
657 (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))] | |
658 "" | |
659 "STSF %1,%0") | |
660 | |
661 ;; Same comment as for truncdfsf2. | |
662 (define_expand "extendsfdf2" | |
111 | 663 [(set (match_operand:DF 0 "register_operand") |
664 (float_extend:DF (match_operand:SF 1 "nonimmediate_operand")))] | |
0 | 665 "" |
666 " | |
667 { | |
668 if (GET_CODE (operands[1]) != MEM) | |
669 { | |
670 rtx stack_slot; | |
671 | |
672 /* There is no sane destination but a register here, if it wasn't | |
673 already MEM. (It's too hard to get fatal_insn to work here.) */ | |
674 if (! REG_P (operands[0])) | |
675 internal_error (\"MMIX Internal: Bad extendsfdf2 expansion\"); | |
676 | |
677 /* FIXME: This stack-slot remains even at -O3. There must be a | |
678 better way. */ | |
679 stack_slot | |
680 = validize_mem (assign_stack_temp (SFmode, | |
111 | 681 GET_MODE_SIZE (SFmode))); |
0 | 682 emit_move_insn (stack_slot, operands[1]); |
683 emit_insn (gen_extendsfdf2 (operands[0], stack_slot)); | |
684 DONE; | |
685 } | |
686 }") | |
687 | |
688 (define_insn "*extendsfdf2_real" | |
689 [(set (match_operand:DF 0 "register_operand" "=r") | |
690 (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))] | |
691 "" | |
692 "LDSF %0,%1") | |
693 | |
694 ;; Neither sign-extend nor zero-extend are necessary; gcc knows how to | |
695 ;; synthesize using shifts or and, except with a memory source and not | |
696 ;; completely optimal. FIXME: Actually, other bugs surface when those | |
697 ;; patterns are defined; fix later. | |
698 | |
699 ;; There are no sane values with the bit-patterns of (int) 0..255 except | |
700 ;; 0 to use in movdfcc. | |
701 | |
702 (define_expand "movdfcc" | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
703 [(set (match_dup 4) (match_dup 5)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
704 (set (match_operand:DF 0 "register_operand" "") |
0 | 705 (if_then_else:DF |
706 (match_operand 1 "comparison_operator" "") | |
707 (match_operand:DF 2 "mmix_reg_or_0_operand" "") | |
708 (match_operand:DF 3 "mmix_reg_or_0_operand" "")))] | |
709 "" | |
710 " | |
711 { | |
712 enum rtx_code code = GET_CODE (operands[1]); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
713 if (code == LE || code == GE) |
0 | 714 FAIL; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
715 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
716 operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
717 XEXP (operands[1], 1)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
718 operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
719 XEXP (operands[1], 0), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
720 XEXP (operands[1], 1)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
721 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); |
0 | 722 }") |
723 | |
724 (define_expand "movdicc" | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
725 [(set (match_dup 4) (match_dup 5)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
726 (set (match_operand:DI 0 "register_operand" "") |
0 | 727 (if_then_else:DI |
728 (match_operand 1 "comparison_operator" "") | |
729 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "") | |
730 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "")))] | |
731 "" | |
732 " | |
733 { | |
734 enum rtx_code code = GET_CODE (operands[1]); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
735 if (code == LE || code == GE) |
0 | 736 FAIL; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
737 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
738 operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
739 XEXP (operands[1], 1)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
740 operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
741 XEXP (operands[1], 0), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
742 XEXP (operands[1], 1)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
743 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); |
0 | 744 }") |
745 | |
746 ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode? | |
747 (define_insn "*movdicc_real_foldable" | |
748 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") | |
749 (if_then_else:DI | |
750 (match_operator 2 "mmix_foldable_comparison_operator" | |
751 [(match_operand:DI 3 "register_operand" "r,r,r,r") | |
752 (const_int 0)]) | |
753 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM") | |
754 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))] | |
755 "" | |
756 "@ | |
757 CS%d2 %0,%3,%1 | |
758 CS%D2 %0,%3,%4 | |
759 ZS%d2 %0,%3,%1 | |
760 ZS%D2 %0,%3,%4") | |
761 | |
762 (define_insn "*movdicc_real_reversible" | |
763 [(set | |
764 (match_operand:DI 0 "register_operand" "=r ,r ,r ,r") | |
765 (if_then_else:DI | |
766 (match_operator | |
767 2 "mmix_comparison_operator" | |
768 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r") | |
769 (const_int 0)]) | |
770 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM") | |
771 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))] | |
772 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))" | |
773 "@ | |
774 CS%d2 %0,%3,%1 | |
775 CS%D2 %0,%3,%4 | |
776 ZS%d2 %0,%3,%1 | |
777 ZS%D2 %0,%3,%4") | |
778 | |
779 (define_insn "*movdicc_real_nonreversible" | |
780 [(set | |
781 (match_operand:DI 0 "register_operand" "=r ,r") | |
782 (if_then_else:DI | |
783 (match_operator | |
784 2 "mmix_comparison_operator" | |
785 [(match_operand 3 "mmix_reg_cc_operand" "r ,r") | |
786 (const_int 0)]) | |
787 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,rI") | |
788 (match_operand:DI 4 "mmix_reg_or_0_operand" "0 ,GM")))] | |
789 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))" | |
790 "@ | |
791 CS%d2 %0,%3,%1 | |
792 ZS%d2 %0,%3,%1") | |
793 | |
794 (define_insn "*movdfcc_real_foldable" | |
795 [(set | |
796 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r") | |
797 (if_then_else:DF | |
798 (match_operator | |
799 2 "mmix_foldable_comparison_operator" | |
800 [(match_operand:DI 3 "register_operand" "r ,r ,r ,r") | |
801 (const_int 0)]) | |
802 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM") | |
803 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))] | |
804 "" | |
805 "@ | |
806 CS%d2 %0,%3,%1 | |
807 CS%D2 %0,%3,%4 | |
808 ZS%d2 %0,%3,%1 | |
809 ZS%D2 %0,%3,%4") | |
810 | |
811 (define_insn "*movdfcc_real_reversible" | |
812 [(set | |
813 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r") | |
814 (if_then_else:DF | |
815 (match_operator | |
816 2 "mmix_comparison_operator" | |
817 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r") | |
818 (const_int 0)]) | |
819 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM") | |
820 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))] | |
821 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))" | |
822 "@ | |
823 CS%d2 %0,%3,%1 | |
824 CS%D2 %0,%3,%4 | |
825 ZS%d2 %0,%3,%1 | |
826 ZS%D2 %0,%3,%4") | |
827 | |
828 (define_insn "*movdfcc_real_nonreversible" | |
829 [(set | |
830 (match_operand:DF 0 "register_operand" "=r ,r") | |
831 (if_then_else:DF | |
832 (match_operator | |
833 2 "mmix_comparison_operator" | |
834 [(match_operand 3 "mmix_reg_cc_operand" "r ,r") | |
835 (const_int 0)]) | |
836 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,rGM") | |
837 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,GM")))] | |
838 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))" | |
839 "@ | |
840 CS%d2 %0,%3,%1 | |
841 ZS%d2 %0,%3,%1") | |
842 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
843 ;; FIXME: scc insns will probably help, I just skip them |
0 | 844 ;; right now. Revisit. |
845 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
846 (define_expand "cbranchdi4" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
847 [(set (match_dup 4) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
848 (match_op_dup 5 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
849 [(match_operand:DI 1 "register_operand" "") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
850 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")])) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
851 (set (pc) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
852 (if_then_else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
853 (match_operator 0 "ordered_comparison_operator" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
854 [(match_dup 4) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
855 (const_int 0)]) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
856 (label_ref (match_operand 3 "" "")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
857 (pc)))] |
0 | 858 "" |
859 " | |
860 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
861 operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
862 operands[1], operands[2]); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
863 operands[5] = gen_rtx_fmt_ee (COMPARE, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
864 GET_MODE (operands[4]), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
865 operands[1], operands[2]); |
0 | 866 }") |
867 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
868 (define_expand "cbranchdf4" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
869 [(set (match_dup 4) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
870 (match_op_dup 5 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
871 [(match_operand:DF 1 "register_operand" "") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
872 (match_operand:DF 2 "register_operand" "")])) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
873 (set (pc) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
874 (if_then_else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
875 (match_operator 0 "float_comparison_operator" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
876 [(match_dup 4) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
877 (const_int 0)]) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
878 (label_ref (match_operand 3 "" "")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
879 (pc)))] |
0 | 880 "" |
881 " | |
882 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
883 /* The head comment of optabs.c:can_compare_p says we're required to |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
884 implement this, so we have to clean up the mess here. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
885 if (GET_CODE (operands[0]) == LE || GET_CODE (operands[0]) == GE) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
886 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
887 enum rtx_code ltgt_code = GET_CODE (operands[0]) == LE ? LT : GT; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
888 emit_cmp_and_jump_insns (operands[1], operands[2], ltgt_code, NULL_RTX, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
889 DFmode, 0, operands[3]); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
890 emit_cmp_and_jump_insns (operands[1], operands[2], EQ, NULL_RTX, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
891 DFmode, 0, operands[3]); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
892 DONE; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
893 } |
0 | 894 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
895 operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
896 operands[1], operands[2]); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
897 operands[5] = gen_rtx_fmt_ee (COMPARE, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
898 GET_MODE (operands[4]), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
899 operands[1], operands[2]); |
0 | 900 }") |
901 | |
902 | |
903 ;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but | |
904 ;; there's no RTL code for it. Maybe revisit in future. | |
905 | |
906 ;; FIXME: Odd/Even matchers? | |
907 (define_insn "*bCC_foldable" | |
908 [(set (pc) | |
909 (if_then_else | |
910 (match_operator 1 "mmix_foldable_comparison_operator" | |
911 [(match_operand:DI 2 "register_operand" "r") | |
912 (const_int 0)]) | |
913 (label_ref (match_operand 0 "" "")) | |
914 (pc)))] | |
915 "" | |
916 "%+B%d1 %2,%0") | |
917 | |
918 (define_insn "*bCC" | |
919 [(set (pc) | |
920 (if_then_else | |
921 (match_operator 1 "mmix_comparison_operator" | |
922 [(match_operand 2 "mmix_reg_cc_operand" "r") | |
923 (const_int 0)]) | |
924 (label_ref (match_operand 0 "" "")) | |
925 (pc)))] | |
926 "" | |
927 "%+B%d1 %2,%0") | |
928 | |
929 (define_insn "*bCC_inverted_foldable" | |
930 [(set (pc) | |
931 (if_then_else | |
932 (match_operator 1 "mmix_foldable_comparison_operator" | |
933 [(match_operand:DI 2 "register_operand" "r") | |
934 (const_int 0)]) | |
935 (pc) | |
936 (label_ref (match_operand 0 "" ""))))] | |
937 ;; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator. | |
938 "" | |
939 "%+B%D1 %2,%0") | |
940 | |
941 (define_insn "*bCC_inverted" | |
942 [(set (pc) | |
943 (if_then_else | |
944 (match_operator 1 "mmix_comparison_operator" | |
945 [(match_operand 2 "mmix_reg_cc_operand" "r") | |
946 (const_int 0)]) | |
947 (pc) | |
948 (label_ref (match_operand 0 "" ""))))] | |
949 "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))" | |
950 "%+B%D1 %2,%0") | |
951 | |
952 (define_expand "call" | |
953 [(parallel [(call (match_operand:QI 0 "memory_operand" "") | |
954 (match_operand 1 "general_operand" "")) | |
955 (use (match_operand 2 "general_operand" "")) | |
956 (clobber (match_dup 4))]) | |
957 (set (match_dup 4) (match_dup 3))] | |
958 "" | |
959 " | |
960 { | |
961 /* The caller checks that the operand is generally valid as an | |
962 address, but at -O0 nothing makes sure that it's also a valid | |
963 call address for a *call*; a mmix_symbolic_or_address_operand. | |
964 Force into a register if it isn't. */ | |
965 if (!mmix_symbolic_or_address_operand (XEXP (operands[0], 0), | |
966 GET_MODE (XEXP (operands[0], 0)))) | |
967 operands[0] | |
968 = replace_equiv_address (operands[0], | |
969 force_reg (Pmode, XEXP (operands[0], 0))); | |
970 | |
971 /* Since the epilogue 'uses' the return address, and it is clobbered | |
972 in the call, and we set it back after every call (all but one setting | |
973 will be optimized away), integrity is maintained. */ | |
974 operands[3] | |
975 = mmix_get_hard_reg_initial_val (Pmode, | |
976 MMIX_INCOMING_RETURN_ADDRESS_REGNUM); | |
977 | |
978 /* FIXME: There's a bug in gcc which causes NULL to be passed as | |
979 operand[2] when we get out of registers, which later confuses gcc. | |
980 Work around it by replacing it with const_int 0. Possibly documentation | |
981 error too. */ | |
982 if (operands[2] == NULL_RTX) | |
983 operands[2] = const0_rtx; | |
984 | |
985 operands[4] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); | |
986 }") | |
987 | |
988 (define_expand "call_value" | |
989 [(parallel [(set (match_operand 0 "" "") | |
990 (call (match_operand:QI 1 "memory_operand" "") | |
991 (match_operand 2 "general_operand" ""))) | |
992 (use (match_operand 3 "general_operand" "")) | |
993 (clobber (match_dup 5))]) | |
994 (set (match_dup 5) (match_dup 4))] | |
995 "" | |
996 " | |
997 { | |
998 /* The caller checks that the operand is generally valid as an | |
999 address, but at -O0 nothing makes sure that it's also a valid | |
1000 call address for a *call*; a mmix_symbolic_or_address_operand. | |
1001 Force into a register if it isn't. */ | |
1002 if (!mmix_symbolic_or_address_operand (XEXP (operands[1], 0), | |
1003 GET_MODE (XEXP (operands[1], 0)))) | |
1004 operands[1] | |
1005 = replace_equiv_address (operands[1], | |
1006 force_reg (Pmode, XEXP (operands[1], 0))); | |
1007 | |
1008 /* Since the epilogue 'uses' the return address, and it is clobbered | |
1009 in the call, and we set it back after every call (all but one setting | |
1010 will be optimized away), integrity is maintained. */ | |
1011 operands[4] | |
1012 = mmix_get_hard_reg_initial_val (Pmode, | |
1013 MMIX_INCOMING_RETURN_ADDRESS_REGNUM); | |
1014 | |
1015 /* FIXME: See 'call'. */ | |
1016 if (operands[3] == NULL_RTX) | |
1017 operands[3] = const0_rtx; | |
1018 | |
1019 /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the | |
1020 *next* argument register, not the number of arguments in registers. | |
1021 (There used to be code here where that mattered.) */ | |
1022 | |
1023 operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); | |
1024 }") | |
1025 | |
1026 ;; Don't use 'p' here. A 'p' must stand first in constraints, or reload | |
1027 ;; messes up, not registering the address for reload. Several C++ | |
1028 ;; testcases, including g++.brendan/crash40.C. FIXME: This is arguably a | |
1029 ;; bug in gcc. Note line ~2612 in reload.c, that does things on the | |
1030 ;; condition <<else if (constraints[i][0] == 'p')>> and the comment on | |
1031 ;; ~3017 that says: | |
1032 ;; << case 'p': | |
1033 ;; /* All necessary reloads for an address_operand | |
1034 ;; were handled in find_reloads_address. */>> | |
1035 ;; Sorry, I have not dug deeper. If symbolic addresses are used | |
1036 ;; rarely compared to addresses in registers, disparaging the | |
1037 ;; first ("p") alternative by adding ? in the first operand | |
1038 ;; might do the trick. We define 'U' as a synonym to 'p', but without the | |
1039 ;; caveats (and very small advantages) of 'p'. | |
111 | 1040 ;; As of r190682 still so: newlib/libc/stdlib/dtoa.c ICEs if "p" is used. |
0 | 1041 (define_insn "*call_real" |
1042 [(call (mem:QI | |
1043 (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU")) | |
1044 (match_operand 1 "" "")) | |
1045 (use (match_operand 2 "" "")) | |
1046 (clobber (reg:DI MMIX_rJ_REGNUM))] | |
1047 "" | |
1048 "@ | |
1049 PUSHJ $%p2,%0 | |
1050 PUSHGO $%p2,%a0") | |
1051 | |
1052 (define_insn "*call_value_real" | |
1053 [(set (match_operand 0 "register_operand" "=r,r") | |
1054 (call (mem:QI | |
1055 (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU")) | |
1056 (match_operand 2 "" ""))) | |
1057 (use (match_operand 3 "" "")) | |
1058 (clobber (reg:DI MMIX_rJ_REGNUM))] | |
1059 "" | |
1060 "@ | |
1061 PUSHJ $%p3,%1 | |
1062 PUSHGO $%p3,%a1") | |
1063 | |
1064 ;; I hope untyped_call and untyped_return are not needed for MMIX. | |
1065 ;; Users of Objective-C will notice. | |
1066 | |
1067 ; Generated by GCC. | |
1068 (define_expand "return" | |
1069 [(return)] | |
1070 "mmix_use_simple_return ()" | |
1071 "") | |
1072 | |
1073 ; Generated by the epilogue expander. | |
1074 (define_insn "*expanded_return" | |
1075 [(return)] | |
1076 "" | |
1077 "POP %.,0") | |
1078 | |
1079 (define_expand "prologue" | |
1080 [(const_int 0)] | |
1081 "" | |
1082 "mmix_expand_prologue (); DONE;") | |
1083 | |
1084 ; Note that the (return) from the expander itself is always the last insn | |
1085 ; in the epilogue. | |
1086 (define_expand "epilogue" | |
1087 [(return)] | |
1088 "" | |
1089 "mmix_expand_epilogue ();") | |
1090 | |
1091 (define_insn "nop" | |
1092 [(const_int 0)] | |
1093 "" | |
1094 "SWYM 0,0,0") | |
1095 | |
1096 (define_insn "jump" | |
1097 [(set (pc) (label_ref (match_operand 0 "" "")))] | |
1098 "" | |
1099 "JMP %0") | |
1100 | |
1101 (define_insn "indirect_jump" | |
1102 [(set (pc) (match_operand 0 "address_operand" "p"))] | |
1103 "" | |
1104 "GO $255,%a0") | |
1105 | |
1106 ;; FIXME: This is just a jump, and should be expanded to one. | |
1107 (define_insn "tablejump" | |
1108 [(set (pc) (match_operand:DI 0 "address_operand" "p")) | |
1109 (use (label_ref (match_operand 1 "" "")))] | |
1110 "" | |
1111 "GO $255,%a0") | |
1112 | |
1113 ;; The only peculiar thing is that the register stack has to be unwound at | |
1114 ;; nonlocal_goto_receiver. At each function that has a nonlocal label, we | |
1115 ;; save at function entry the location of the "alpha" register stack | |
1116 ;; pointer, rO, in a stack slot known to that function (right below where | |
1117 ;; the frame-pointer would be located). | |
1118 ;; In the nonlocal goto receiver, we unwind the register stack by a series | |
1119 ;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we | |
1120 ;; should die with a trap.) | |
1121 (define_expand "nonlocal_goto_receiver" | |
111 | 1122 [(parallel [(unspec_volatile [(match_dup 1)] 1) |
0 | 1123 (clobber (scratch:DI)) |
1124 (clobber (reg:DI MMIX_rJ_REGNUM))]) | |
1125 (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))] | |
1126 "" | |
1127 " | |
1128 { | |
1129 operands[0] | |
1130 = mmix_get_hard_reg_initial_val (Pmode, | |
1131 MMIX_INCOMING_RETURN_ADDRESS_REGNUM); | |
1132 | |
111 | 1133 /* We need the frame-pointer to be live or the equivalent |
1134 expression, so refer to it in the pattern. We can't use a MEM | |
1135 (that may contain out-of-range offsets in the final expression) | |
1136 for fear that middle-end will legitimize it or replace the address | |
1137 using temporary registers (which are not revived at this point). */ | |
1138 operands[1] = frame_pointer_rtx; | |
1139 | |
0 | 1140 /* Mark this function as containing a landing-pad. */ |
1141 cfun->machine->has_landing_pad = 1; | |
1142 }") | |
1143 | |
1144 ;; GCC can insist on using saved registers to keep the slot address in | |
1145 ;; "across" the exception, or (perhaps) to use saved registers in the | |
1146 ;; address and re-use them after the register stack unwind, so it's best | |
1147 ;; to form the address ourselves. | |
1148 (define_insn "*nonlocal_goto_receiver_expanded" | |
111 | 1149 [(unspec_volatile [(match_operand:DI 1 "frame_pointer_operand" "Yf")] 1) |
0 | 1150 (clobber (match_scratch:DI 0 "=&r")) |
1151 (clobber (reg:DI MMIX_rJ_REGNUM))] | |
1152 "" | |
1153 { | |
111 | 1154 rtx my_operands[3]; |
0 | 1155 const char *my_template |
1156 = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\ | |
1157 0:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:"; | |
1158 | |
111 | 1159 my_operands[1] = operands[0]; |
1160 my_operands[2] = GEN_INT (-MMIX_fp_rO_OFFSET); | |
0 | 1161 |
111 | 1162 if (operands[1] == hard_frame_pointer_rtx) |
0 | 1163 { |
111 | 1164 mmix_output_register_setting (asm_out_file, REGNO (operands[0]), |
1165 MMIX_fp_rO_OFFSET, 1); | |
1166 my_operands[0] | |
1167 = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, operands[0]); | |
0 | 1168 } |
1169 else | |
1170 { | |
111 | 1171 int64_t offs = INTVAL (XEXP (operands[1], 1)); |
1172 offs += MMIX_fp_rO_OFFSET; | |
0 | 1173 |
111 | 1174 if (insn_const_int_ok_for_constraint (offs, CONSTRAINT_I)) |
0 | 1175 my_operands[0] |
1176 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs)); | |
1177 else | |
1178 { | |
111 | 1179 mmix_output_register_setting (asm_out_file, REGNO (operands[0]), |
0 | 1180 offs, 1); |
111 | 1181 my_operands[0] |
1182 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, operands[0]); | |
0 | 1183 } |
1184 } | |
1185 | |
1186 output_asm_insn (my_template, my_operands); | |
1187 return ""; | |
1188 }) | |
1189 | |
1190 (define_insn "*Naddu" | |
1191 [(set (match_operand:DI 0 "register_operand" "=r") | |
1192 (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r") | |
1193 (match_operand:DI 2 "const_int_operand" "n")) | |
1194 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))] | |
1195 "GET_CODE (operands[2]) == CONST_INT | |
1196 && (INTVAL (operands[2]) == 2 | |
1197 || INTVAL (operands[2]) == 4 | |
1198 || INTVAL (operands[2]) == 8 | |
1199 || INTVAL (operands[2]) == 16)" | |
1200 "%2ADDU %0,%1,%3") | |
1201 | |
1202 (define_insn "*andn" | |
1203 [(set (match_operand:DI 0 "register_operand" "=r") | |
1204 (and:DI | |
1205 (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")) | |
1206 (match_operand:DI 2 "register_operand" "r")))] | |
1207 "" | |
1208 "ANDN %0,%2,%1") | |
1209 | |
1210 (define_insn "*nand" | |
1211 [(set (match_operand:DI 0 "register_operand" "=r") | |
1212 (ior:DI | |
1213 (not:DI (match_operand:DI 1 "register_operand" "%r")) | |
1214 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] | |
1215 "" | |
1216 "NAND %0,%1,%2") | |
1217 | |
1218 (define_insn "*nor" | |
1219 [(set (match_operand:DI 0 "register_operand" "=r") | |
1220 (and:DI | |
1221 (not:DI (match_operand:DI 1 "register_operand" "%r")) | |
1222 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] | |
1223 "" | |
1224 "NOR %0,%1,%2") | |
1225 | |
1226 (define_insn "*nxor" | |
1227 [(set (match_operand:DI 0 "register_operand" "=r") | |
1228 (not:DI | |
1229 (xor:DI (match_operand:DI 1 "register_operand" "%r") | |
1230 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] | |
1231 "" | |
1232 "NXOR %0,%1,%2") | |
1233 | |
1234 (define_insn "sync_icache" | |
1235 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m") | |
1236 (match_operand:DI 1 "const_int_operand" "I")] 0)] | |
1237 "" | |
1238 "SYNCID %1,%0") | |
1239 | |
1240 ;; Local Variables: | |
1241 ;; mode: lisp | |
1242 ;; indent-tabs-mode: t | |
1243 ;; End: |